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
,
252 /* Nothing is waiting so try to complete a pending disconnect */
253 RetryDisconnectCompletion(FCB
);
256 SocketStateUnlock( FCB
);
258 return STATUS_SUCCESS
;
261 static IO_COMPLETION_ROUTINE PacketSocketSendComplete
;
262 static NTSTATUS NTAPI PacketSocketSendComplete
263 ( PDEVICE_OBJECT DeviceObject
,
266 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
267 PLIST_ENTRY NextIrpEntry
;
269 PAFD_SEND_INFO SendReq
;
271 UNREFERENCED_PARAMETER(DeviceObject
);
273 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %u bytes used\n",
274 Irp
->IoStatus
.Status
,
275 Irp
->IoStatus
.Information
));
277 if( !SocketAcquireStateLock( FCB
) )
278 return STATUS_FILE_CLOSED
;
280 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
281 FCB
->SendIrp
.InFlightRequest
= NULL
;
282 /* Request is not in flight any longer */
284 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
285 /* Cleanup our IRP queue because the FCB is being destroyed */
286 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
287 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
288 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
289 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
290 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
291 NextIrp
->IoStatus
.Information
= 0;
292 (void)IoSetCancelRoutine(NextIrp
, NULL
);
293 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
294 UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
295 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
297 SocketStateUnlock( FCB
);
298 return STATUS_FILE_CLOSED
;
301 ASSERT(!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]));
303 /* TDI spec guarantees FIFO ordering on IRPs */
304 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
305 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
307 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
309 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
310 NextIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
312 (void)IoSetCancelRoutine(NextIrp
, NULL
);
314 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
316 UnlockRequest(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
318 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
320 FCB
->PollState
|= AFD_EVENT_SEND
;
321 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
322 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
324 SocketStateUnlock(FCB
);
326 return STATUS_SUCCESS
;
330 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
331 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
332 NTSTATUS Status
= STATUS_SUCCESS
;
333 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
334 PAFD_FCB FCB
= FileObject
->FsContext
;
335 PAFD_SEND_INFO SendReq
;
336 UINT TotalBytesCopied
= 0, i
, SpaceAvail
= 0, BytesCopied
, SendLength
;
337 KPROCESSOR_MODE LockMode
;
339 UNREFERENCED_PARAMETER(DeviceObject
);
340 UNREFERENCED_PARAMETER(Short
);
342 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
344 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
346 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
348 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
350 PAFD_SEND_INFO_UDP SendReq
;
351 PTDI_CONNECTION_INFORMATION TargetAddress
;
353 /* Check that the socket is bound */
354 if( FCB
->State
!= SOCKET_STATE_BOUND
|| !FCB
->RemoteAddress
)
356 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
357 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
, Irp
,
361 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
362 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
364 /* Must lock buffers before handing off user data */
365 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
366 SendReq
->BufferCount
,
368 FALSE
, FALSE
, LockMode
);
370 if( !SendReq
->BufferArray
) {
371 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
375 Status
= TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
377 if( NT_SUCCESS(Status
) ) {
378 FCB
->PollState
&= ~AFD_EVENT_SEND
;
380 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
381 if (Status
== STATUS_PENDING
)
383 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
384 FCB
->AddressFile
.Object
,
385 SendReq
->BufferArray
[0].buf
,
386 SendReq
->BufferArray
[0].len
,
389 PacketSocketSendComplete
,
393 ExFreePool( TargetAddress
);
395 SocketStateUnlock(FCB
);
397 return STATUS_PENDING
;
401 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
402 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
406 if (FCB
->PollState
& AFD_EVENT_CLOSE
)
408 AFD_DbgPrint(MIN_TRACE
,("Connection reset by remote peer\n"));
410 /* This is an unexpected remote disconnect */
411 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
414 if (FCB
->PollState
& AFD_EVENT_ABORT
)
416 AFD_DbgPrint(MIN_TRACE
,("Connection aborted\n"));
418 /* This is an abortive socket closure on our side */
419 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
424 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
426 /* This is a graceful send closure */
427 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
430 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
431 return UnlockAndMaybeComplete
432 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
434 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
435 SendReq
->BufferCount
,
437 FALSE
, FALSE
, LockMode
);
439 if( !SendReq
->BufferArray
) {
440 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
444 AFD_DbgPrint(MID_TRACE
,("Socket state %u\n", FCB
->State
));
446 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
447 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
) &&
448 ((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
449 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
450 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
451 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
453 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
454 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
458 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %u\n",
459 FCB
->Send
.BytesUsed
));
461 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
463 AFD_DbgPrint(MID_TRACE
,("We can accept %u bytes\n",
466 /* Count the total transfer size */
468 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
470 SendLength
+= SendReq
->BufferArray
[i
].len
;
473 /* Make sure we've got the space */
474 if (SendLength
> SpaceAvail
)
476 /* Blocking sockets have to wait here */
477 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
479 FCB
->PollState
&= ~AFD_EVENT_SEND
;
480 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
483 /* Check if we can send anything */
486 FCB
->PollState
&= ~AFD_EVENT_SEND
;
488 /* Non-overlapped sockets will fail if we can send nothing */
489 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
))
491 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
492 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
496 /* Overlapped sockets just pend */
497 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
502 for ( i
= 0; SpaceAvail
> 0 && i
< SendReq
->BufferCount
; i
++ )
504 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
506 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %u, %p:%u to %p\n",
508 SendReq
->BufferArray
[i
].buf
,
510 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
512 RtlCopyMemory(FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
513 SendReq
->BufferArray
[i
].buf
,
516 TotalBytesCopied
+= BytesCopied
;
517 SpaceAvail
-= BytesCopied
;
518 FCB
->Send
.BytesUsed
+= BytesCopied
;
521 Irp
->IoStatus
.Information
= TotalBytesCopied
;
523 if( TotalBytesCopied
== 0 ) {
524 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
525 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
526 return UnlockAndMaybeComplete
527 ( FCB
, STATUS_SUCCESS
, Irp
, TotalBytesCopied
);
532 FCB
->PollState
|= AFD_EVENT_SEND
;
533 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
534 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
538 FCB
->PollState
&= ~AFD_EVENT_SEND
;
541 /* We use the IRP tail for some temporary storage here */
542 Irp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)Irp
->IoStatus
.Information
;
544 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
545 if (Status
== STATUS_PENDING
&& !FCB
->SendIrp
.InFlightRequest
)
547 TdiSend(&FCB
->SendIrp
.InFlightRequest
,
548 FCB
->Connection
.Object
,
557 SocketStateUnlock(FCB
);
559 return STATUS_PENDING
;
563 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
564 PIO_STACK_LOCATION IrpSp
) {
565 NTSTATUS Status
= STATUS_SUCCESS
;
566 PTDI_CONNECTION_INFORMATION TargetAddress
;
567 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
568 PAFD_FCB FCB
= FileObject
->FsContext
;
569 PAFD_SEND_INFO_UDP SendReq
;
570 KPROCESSOR_MODE LockMode
;
572 UNREFERENCED_PARAMETER(DeviceObject
);
574 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
576 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
578 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
580 /* Check that the socket is bound */
581 if( FCB
->State
!= SOCKET_STATE_BOUND
&&
582 FCB
->State
!= SOCKET_STATE_CREATED
)
584 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
585 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
590 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
591 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
594 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
595 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
597 if (FCB
->State
== SOCKET_STATE_CREATED
)
599 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
601 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
602 Address
[0].AddressType
);
604 if( FCB
->LocalAddress
) {
605 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
607 if( NT_SUCCESS(Status
) )
608 FCB
->State
= SOCKET_STATE_BOUND
;
610 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
612 return UnlockAndMaybeComplete
613 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
616 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
617 SendReq
->BufferCount
,
619 FALSE
, FALSE
, LockMode
);
621 if( !SendReq
->BufferArray
)
622 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
626 (MID_TRACE
,("RemoteAddress #%d Type %u\n",
627 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
629 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
630 Address
[0].AddressType
));
632 Status
= TdiBuildConnectionInfo( &TargetAddress
,
633 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
) );
635 /* Check the size of the Address given ... */
637 if( NT_SUCCESS(Status
) ) {
638 FCB
->PollState
&= ~AFD_EVENT_SEND
;
640 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
641 if (Status
== STATUS_PENDING
)
643 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
644 FCB
->AddressFile
.Object
,
645 SendReq
->BufferArray
[0].buf
,
646 SendReq
->BufferArray
[0].len
,
649 PacketSocketSendComplete
,
653 ExFreePool(TargetAddress
);
655 SocketStateUnlock(FCB
);
657 return STATUS_PENDING
;
661 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
662 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );