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)
12 static IO_COMPLETION_ROUTINE SendComplete
;
13 static NTSTATUS NTAPI SendComplete
14 ( PDEVICE_OBJECT DeviceObject
,
17 NTSTATUS Status
= Irp
->IoStatus
.Status
;
18 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
19 PLIST_ENTRY NextIrpEntry
;
21 PIO_STACK_LOCATION NextIrpSp
;
22 PAFD_SEND_INFO SendReq
= NULL
;
24 UINT TotalBytesCopied
= 0, TotalBytesProcessed
= 0, SpaceAvail
, i
;
25 UINT SendLength
, BytesCopied
;
26 BOOLEAN HaltSendQueue
;
28 UNREFERENCED_PARAMETER(DeviceObject
);
31 * The Irp parameter passed in is the IRP of the stream between AFD and
32 * TDI driver. It's not very usefull to us. We need the IRPs of the stream
33 * between usermode and AFD. Those are chained from
34 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
35 * below as "NextIrp" ('cause they are the next usermode IRP to be
39 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %u bytes used\n",
41 Irp
->IoStatus
.Information
));
43 if( !SocketAcquireStateLock( FCB
) )
44 return STATUS_FILE_CLOSED
;
46 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
47 FCB
->SendIrp
.InFlightRequest
= NULL
;
48 /* Request is not in flight any longer */
50 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
51 /* Cleanup our IRP queue because the FCB is being destroyed */
52 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
53 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
54 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
55 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
56 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
57 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
58 NextIrp
->IoStatus
.Information
= 0;
59 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
60 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
61 (void)IoSetCancelRoutine(NextIrp
, NULL
);
62 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
65 RetryDisconnectCompletion(FCB
);
67 SocketStateUnlock( FCB
);
68 return STATUS_FILE_CLOSED
;
71 if( !NT_SUCCESS(Status
) ) {
72 /* Complete all following send IRPs with error */
74 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
76 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
78 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
79 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
80 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
82 UnlockBuffers( SendReq
->BufferArray
,
86 NextIrp
->IoStatus
.Status
= Status
;
87 NextIrp
->IoStatus
.Information
= 0;
89 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
90 (void)IoSetCancelRoutine(NextIrp
, NULL
);
91 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
94 RetryDisconnectCompletion(FCB
);
96 SocketStateUnlock( FCB
);
98 return STATUS_SUCCESS
;
101 RtlMoveMemory( FCB
->Send
.Window
,
102 FCB
->Send
.Window
+ Irp
->IoStatus
.Information
,
103 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
105 TotalBytesProcessed
= 0;
106 SendLength
= Irp
->IoStatus
.Information
;
107 HaltSendQueue
= FALSE
;
108 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && SendLength
> 0) {
109 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
110 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
111 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
112 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
113 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
115 TotalBytesCopied
= (ULONG_PTR
)NextIrp
->Tail
.Overlay
.DriverContext
[3];
116 ASSERT(TotalBytesCopied
!= 0);
118 /* If we didn't get enough, keep waiting */
119 if (TotalBytesCopied
> SendLength
)
121 /* Update the bytes left to copy */
122 TotalBytesCopied
-= SendLength
;
123 NextIrp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)TotalBytesCopied
;
125 /* Update the state variables */
126 FCB
->Send
.BytesUsed
-= SendLength
;
127 TotalBytesProcessed
+= SendLength
;
131 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
],
132 &NextIrp
->Tail
.Overlay
.ListEntry
);
133 HaltSendQueue
= TRUE
;
137 ASSERT(NextIrp
->IoStatus
.Information
!= 0);
139 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
141 FCB
->Send
.BytesUsed
-= TotalBytesCopied
;
142 TotalBytesProcessed
+= TotalBytesCopied
;
143 SendLength
-= TotalBytesCopied
;
145 (void)IoSetCancelRoutine(NextIrp
, NULL
);
147 UnlockBuffers( SendReq
->BufferArray
,
148 SendReq
->BufferCount
,
151 if (NextIrp
->MdlAddress
) UnlockRequest(NextIrp
, NextIrpSp
);
153 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
156 ASSERT(SendLength
== 0);
158 if ( !HaltSendQueue
&& !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
159 NextIrpEntry
= FCB
->PendingIrpList
[FUNCTION_SEND
].Flink
;
160 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
161 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
162 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
163 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
165 AFD_DbgPrint(MID_TRACE
,("SendReq @ %p\n", SendReq
));
167 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
168 TotalBytesCopied
= 0;
170 /* Count the total transfer size */
172 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
174 SendLength
+= SendReq
->BufferArray
[i
].len
;
177 /* Make sure we've got the space */
178 if (SendLength
> SpaceAvail
)
180 /* Blocking sockets have to wait here */
181 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
183 FCB
->PollState
&= ~AFD_EVENT_SEND
;
188 /* Check if we can send anything */
191 FCB
->PollState
&= ~AFD_EVENT_SEND
;
193 /* We should never be non-overlapped and get to this point */
194 ASSERT(SendReq
->AfdFlags
& AFD_OVERLAPPED
);
202 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
203 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
205 Map
[i
].BufferAddress
=
206 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
208 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
209 Map
[i
].BufferAddress
,
212 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
214 TotalBytesCopied
+= BytesCopied
;
215 SpaceAvail
-= BytesCopied
;
216 FCB
->Send
.BytesUsed
+= BytesCopied
;
219 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
220 NextIrp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)NextIrp
->IoStatus
.Information
;
224 if (FCB
->Send
.Size
- FCB
->Send
.BytesUsed
!= 0 && !FCB
->SendClosed
&&
225 IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]))
227 FCB
->PollState
|= AFD_EVENT_SEND
;
228 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
229 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
233 FCB
->PollState
&= ~AFD_EVENT_SEND
;
237 /* Some data is still waiting */
238 if( FCB
->Send
.BytesUsed
)
240 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
241 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
,
388 PacketSocketSendComplete
,
392 ExFreePool( TargetAddress
);
394 SocketStateUnlock(FCB
);
396 return STATUS_PENDING
;
400 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
401 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
405 if (FCB
->PollState
& AFD_EVENT_CLOSE
)
407 AFD_DbgPrint(MIN_TRACE
,("Connection reset by remote peer\n"));
409 /* This is an unexpected remote disconnect */
410 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
413 if (FCB
->PollState
& AFD_EVENT_ABORT
)
415 AFD_DbgPrint(MIN_TRACE
,("Connection aborted\n"));
417 /* This is an abortive socket closure on our side */
418 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
423 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
425 /* This is a graceful send closure */
426 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
429 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
430 return UnlockAndMaybeComplete
431 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
433 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
434 SendReq
->BufferCount
,
436 FALSE
, FALSE
, LockMode
);
438 if( !SendReq
->BufferArray
) {
439 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
443 AFD_DbgPrint(MID_TRACE
,("Socket state %u\n", FCB
->State
));
445 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
446 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
) &&
447 ((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
448 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
449 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
450 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
452 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
453 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
457 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %u\n",
458 FCB
->Send
.BytesUsed
));
460 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
462 AFD_DbgPrint(MID_TRACE
,("We can accept %u bytes\n",
465 /* Count the total transfer size */
467 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
469 SendLength
+= SendReq
->BufferArray
[i
].len
;
472 /* Make sure we've got the space */
473 if (SendLength
> SpaceAvail
)
475 /* Blocking sockets have to wait here */
476 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
478 FCB
->PollState
&= ~AFD_EVENT_SEND
;
479 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
482 /* Check if we can send anything */
485 FCB
->PollState
&= ~AFD_EVENT_SEND
;
487 /* Non-overlapped sockets will fail if we can send nothing */
488 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
))
490 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
491 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
495 /* Overlapped sockets just pend */
496 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
501 for ( i
= 0; SpaceAvail
> 0 && i
< SendReq
->BufferCount
; i
++ )
503 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
505 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %u, %p:%u to %p\n",
507 SendReq
->BufferArray
[i
].buf
,
509 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
511 RtlCopyMemory(FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
512 SendReq
->BufferArray
[i
].buf
,
515 TotalBytesCopied
+= BytesCopied
;
516 SpaceAvail
-= BytesCopied
;
517 FCB
->Send
.BytesUsed
+= BytesCopied
;
520 Irp
->IoStatus
.Information
= TotalBytesCopied
;
522 if( TotalBytesCopied
== 0 ) {
523 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
524 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
525 return UnlockAndMaybeComplete
526 ( FCB
, STATUS_SUCCESS
, Irp
, TotalBytesCopied
);
531 FCB
->PollState
|= AFD_EVENT_SEND
;
532 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
533 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
537 FCB
->PollState
&= ~AFD_EVENT_SEND
;
540 /* We use the IRP tail for some temporary storage here */
541 Irp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)Irp
->IoStatus
.Information
;
543 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
544 if (Status
== STATUS_PENDING
&& !FCB
->SendIrp
.InFlightRequest
)
546 TdiSend(&FCB
->SendIrp
.InFlightRequest
,
547 FCB
->Connection
.Object
,
556 SocketStateUnlock(FCB
);
558 return STATUS_PENDING
;
562 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
563 PIO_STACK_LOCATION IrpSp
) {
564 NTSTATUS Status
= STATUS_SUCCESS
;
565 PTDI_CONNECTION_INFORMATION TargetAddress
;
566 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
567 PAFD_FCB FCB
= FileObject
->FsContext
;
568 PAFD_SEND_INFO_UDP SendReq
;
569 KPROCESSOR_MODE LockMode
;
571 UNREFERENCED_PARAMETER(DeviceObject
);
573 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
575 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
577 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
579 /* Check that the socket is bound */
580 if( FCB
->State
!= SOCKET_STATE_BOUND
&&
581 FCB
->State
!= SOCKET_STATE_CREATED
)
583 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
584 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
589 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
590 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
593 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
594 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
596 if (FCB
->State
== SOCKET_STATE_CREATED
)
598 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
600 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
601 Address
[0].AddressType
);
603 if( FCB
->LocalAddress
) {
604 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
606 if( NT_SUCCESS(Status
) )
607 FCB
->State
= SOCKET_STATE_BOUND
;
609 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
611 return UnlockAndMaybeComplete
612 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
615 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
616 SendReq
->BufferCount
,
618 FALSE
, FALSE
, LockMode
);
620 if( !SendReq
->BufferArray
)
621 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
625 (MID_TRACE
,("RemoteAddress #%d Type %u\n",
626 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
628 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
629 Address
[0].AddressType
));
631 Status
= TdiBuildConnectionInfo( &TargetAddress
,
632 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
) );
634 /* Check the size of the Address given ... */
636 if( NT_SUCCESS(Status
) ) {
637 FCB
->PollState
&= ~AFD_EVENT_SEND
;
639 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
640 if (Status
== STATUS_PENDING
)
642 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
643 FCB
->AddressFile
.Object
,
644 SendReq
->BufferArray
[0].buf
,
645 SendReq
->BufferArray
[0].len
,
648 PacketSocketSendComplete
,
652 ExFreePool(TargetAddress
);
654 SocketStateUnlock(FCB
);
656 return STATUS_PENDING
;
660 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
661 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );