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 NTSTATUS NTAPI SendComplete
13 ( PDEVICE_OBJECT DeviceObject
,
16 NTSTATUS Status
= Irp
->IoStatus
.Status
;
17 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
18 PLIST_ENTRY NextIrpEntry
;
20 PIO_STACK_LOCATION NextIrpSp
;
21 PAFD_SEND_INFO SendReq
= NULL
;
23 UINT TotalBytesCopied
= 0, TotalBytesProcessed
= 0, SpaceAvail
, i
;
24 UINT SendLength
, BytesCopied
;
25 BOOLEAN HaltSendQueue
;
28 * The Irp parameter passed in is the IRP of the stream between AFD and
29 * TDI driver. It's not very usefull to us. We need the IRPs of the stream
30 * between usermode and AFD. Those are chained from
31 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
32 * below as "NextIrp" ('cause they are the next usermode IRP to be
36 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
38 Irp
->IoStatus
.Information
));
40 if( !SocketAcquireStateLock( FCB
) )
41 return STATUS_FILE_CLOSED
;
43 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
44 FCB
->SendIrp
.InFlightRequest
= NULL
;
45 /* Request is not in flight any longer */
47 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
48 /* Cleanup our IRP queue because the FCB is being destroyed */
49 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
50 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
51 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
52 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
53 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
54 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
55 NextIrp
->IoStatus
.Information
= 0;
56 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
57 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
58 (void)IoSetCancelRoutine(NextIrp
, NULL
);
59 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
62 RetryDisconnectCompletion(FCB
);
64 SocketStateUnlock( FCB
);
65 return STATUS_FILE_CLOSED
;
68 if( !NT_SUCCESS(Status
) ) {
69 /* Complete all following send IRPs with error */
71 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
73 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
75 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
76 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
77 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
79 UnlockBuffers( SendReq
->BufferArray
,
83 NextIrp
->IoStatus
.Status
= Status
;
84 NextIrp
->IoStatus
.Information
= 0;
86 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
87 (void)IoSetCancelRoutine(NextIrp
, NULL
);
88 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
91 RetryDisconnectCompletion(FCB
);
93 SocketStateUnlock( FCB
);
95 return STATUS_SUCCESS
;
98 RtlMoveMemory( FCB
->Send
.Window
,
99 FCB
->Send
.Window
+ Irp
->IoStatus
.Information
,
100 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
102 TotalBytesProcessed
= 0;
103 SendLength
= Irp
->IoStatus
.Information
;
104 HaltSendQueue
= FALSE
;
105 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && SendLength
> 0) {
106 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
107 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
108 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
109 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
110 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
112 TotalBytesCopied
= (ULONG_PTR
)NextIrp
->Tail
.Overlay
.DriverContext
[3];
113 ASSERT(TotalBytesCopied
!= 0);
115 /* If we didn't get enough, keep waiting */
116 if (TotalBytesCopied
> SendLength
)
118 /* Update the bytes left to copy */
119 TotalBytesCopied
-= SendLength
;
120 NextIrp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)TotalBytesCopied
;
122 /* Update the state variables */
123 FCB
->Send
.BytesUsed
-= SendLength
;
124 TotalBytesProcessed
+= SendLength
;
128 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
],
129 &NextIrp
->Tail
.Overlay
.ListEntry
);
130 HaltSendQueue
= TRUE
;
134 ASSERT(NextIrp
->IoStatus
.Information
!= 0);
136 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
138 FCB
->Send
.BytesUsed
-= TotalBytesCopied
;
139 TotalBytesProcessed
+= TotalBytesCopied
;
140 SendLength
-= TotalBytesCopied
;
142 (void)IoSetCancelRoutine(NextIrp
, NULL
);
144 UnlockBuffers( SendReq
->BufferArray
,
145 SendReq
->BufferCount
,
148 if (NextIrp
->MdlAddress
) UnlockRequest(NextIrp
, NextIrpSp
);
150 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
153 ASSERT(SendLength
== 0);
155 if ( !HaltSendQueue
&& !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
156 NextIrpEntry
= FCB
->PendingIrpList
[FUNCTION_SEND
].Flink
;
157 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
158 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
159 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
160 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
162 AFD_DbgPrint(MID_TRACE
,("SendReq @ %x\n", SendReq
));
164 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
165 TotalBytesCopied
= 0;
167 /* Count the total transfer size */
169 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
171 SendLength
+= SendReq
->BufferArray
[i
].len
;
174 /* Make sure we've got the space */
175 if (SendLength
> SpaceAvail
)
177 /* Blocking sockets have to wait here */
178 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
180 FCB
->PollState
&= ~AFD_EVENT_SEND
;
185 /* Check if we can send anything */
188 FCB
->PollState
&= ~AFD_EVENT_SEND
;
190 /* We should never be non-overlapped and get to this point */
191 ASSERT(SendReq
->AfdFlags
& AFD_OVERLAPPED
);
199 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
200 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
202 Map
[i
].BufferAddress
=
203 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
205 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
206 Map
[i
].BufferAddress
,
209 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
211 TotalBytesCopied
+= BytesCopied
;
212 SpaceAvail
-= BytesCopied
;
213 FCB
->Send
.BytesUsed
+= BytesCopied
;
216 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
217 NextIrp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)NextIrp
->IoStatus
.Information
;
221 if (FCB
->Send
.Size
- FCB
->Send
.BytesUsed
!= 0 && !FCB
->SendClosed
&&
222 IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]))
224 FCB
->PollState
|= AFD_EVENT_SEND
;
225 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
226 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
230 FCB
->PollState
&= ~AFD_EVENT_SEND
;
234 /* Some data is still waiting */
235 if( FCB
->Send
.BytesUsed
)
237 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
238 FCB
->Connection
.Object
,
248 /* Nothing is waiting so try to complete a pending disconnect */
249 RetryDisconnectCompletion(FCB
);
252 SocketStateUnlock( FCB
);
254 return STATUS_SUCCESS
;
257 static NTSTATUS NTAPI PacketSocketSendComplete
258 ( PDEVICE_OBJECT DeviceObject
,
261 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
262 PLIST_ENTRY NextIrpEntry
;
264 PAFD_SEND_INFO SendReq
;
266 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
267 Irp
->IoStatus
.Status
,
268 Irp
->IoStatus
.Information
));
270 if( !SocketAcquireStateLock( FCB
) )
271 return STATUS_FILE_CLOSED
;
273 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
274 FCB
->SendIrp
.InFlightRequest
= NULL
;
275 /* Request is not in flight any longer */
277 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
278 /* Cleanup our IRP queue because the FCB is being destroyed */
279 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
280 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
281 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
282 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
283 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
284 NextIrp
->IoStatus
.Information
= 0;
285 (void)IoSetCancelRoutine(NextIrp
, NULL
);
286 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
287 UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
288 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
290 SocketStateUnlock( FCB
);
291 return STATUS_FILE_CLOSED
;
294 ASSERT(!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]));
296 /* TDI spec guarantees FIFO ordering on IRPs */
297 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
298 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
300 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
302 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
303 NextIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
305 (void)IoSetCancelRoutine(NextIrp
, NULL
);
307 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
309 UnlockRequest(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
311 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
313 FCB
->PollState
|= AFD_EVENT_SEND
;
314 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
315 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
317 SocketStateUnlock(FCB
);
319 return STATUS_SUCCESS
;
323 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
324 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
325 NTSTATUS Status
= STATUS_SUCCESS
;
326 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
327 PAFD_FCB FCB
= FileObject
->FsContext
;
328 PAFD_SEND_INFO SendReq
;
329 UINT TotalBytesCopied
= 0, i
, SpaceAvail
= 0, BytesCopied
, SendLength
;
330 KPROCESSOR_MODE LockMode
;
332 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
334 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
336 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
338 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
340 PAFD_SEND_INFO_UDP SendReq
;
341 PTDI_CONNECTION_INFORMATION TargetAddress
;
343 /* Check that the socket is bound */
344 if( FCB
->State
!= SOCKET_STATE_BOUND
|| !FCB
->RemoteAddress
)
346 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
347 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
, Irp
,
351 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
352 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
354 /* Must lock buffers before handing off user data */
355 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
356 SendReq
->BufferCount
,
358 FALSE
, FALSE
, LockMode
);
360 if( !SendReq
->BufferArray
) {
361 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
365 Status
= TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
367 if( NT_SUCCESS(Status
) ) {
368 FCB
->PollState
&= ~AFD_EVENT_SEND
;
370 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
371 if (Status
== STATUS_PENDING
)
373 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
374 FCB
->AddressFile
.Object
,
375 SendReq
->BufferArray
[0].buf
,
376 SendReq
->BufferArray
[0].len
,
379 PacketSocketSendComplete
,
383 ExFreePool( TargetAddress
);
385 SocketStateUnlock(FCB
);
387 return STATUS_PENDING
;
391 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
392 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
396 if (FCB
->PollState
& AFD_EVENT_CLOSE
)
398 AFD_DbgPrint(MIN_TRACE
,("Connection reset by remote peer\n"));
400 /* This is an unexpected remote disconnect */
401 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
404 if (FCB
->PollState
& AFD_EVENT_ABORT
)
406 AFD_DbgPrint(MIN_TRACE
,("Connection aborted\n"));
408 /* This is an abortive socket closure on our side */
409 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
414 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
416 /* This is a graceful send closure */
417 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
420 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
421 return UnlockAndMaybeComplete
422 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
424 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
425 SendReq
->BufferCount
,
427 FALSE
, FALSE
, LockMode
);
429 if( !SendReq
->BufferArray
) {
430 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
434 AFD_DbgPrint(MID_TRACE
,("Socket state %d\n", FCB
->State
));
436 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
437 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
) &&
438 ((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
439 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
440 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
441 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
443 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
444 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
448 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %d\n",
449 FCB
->Send
.BytesUsed
));
451 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
453 AFD_DbgPrint(MID_TRACE
,("We can accept %d bytes\n",
456 /* Count the total transfer size */
458 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
460 SendLength
+= SendReq
->BufferArray
[i
].len
;
463 /* Make sure we've got the space */
464 if (SendLength
> SpaceAvail
)
466 /* Blocking sockets have to wait here */
467 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
469 FCB
->PollState
&= ~AFD_EVENT_SEND
;
470 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
473 /* Check if we can send anything */
476 FCB
->PollState
&= ~AFD_EVENT_SEND
;
478 /* Non-overlapped sockets will fail if we can send nothing */
479 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
))
481 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
482 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
486 /* Overlapped sockets just pend */
487 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
492 for ( i
= 0; SpaceAvail
> 0 && i
< SendReq
->BufferCount
; i
++ )
494 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
496 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %d, %x:%d to %x\n",
498 SendReq
->BufferArray
[i
].buf
,
500 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
502 RtlCopyMemory(FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
503 SendReq
->BufferArray
[i
].buf
,
506 TotalBytesCopied
+= BytesCopied
;
507 SpaceAvail
-= BytesCopied
;
508 FCB
->Send
.BytesUsed
+= BytesCopied
;
511 Irp
->IoStatus
.Information
= TotalBytesCopied
;
513 if( TotalBytesCopied
== 0 ) {
514 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
515 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
516 return UnlockAndMaybeComplete
517 ( FCB
, STATUS_SUCCESS
, Irp
, TotalBytesCopied
);
522 FCB
->PollState
|= AFD_EVENT_SEND
;
523 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
524 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
528 FCB
->PollState
&= ~AFD_EVENT_SEND
;
531 /* We use the IRP tail for some temporary storage here */
532 Irp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)Irp
->IoStatus
.Information
;
534 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
535 if (Status
== STATUS_PENDING
&& !FCB
->SendIrp
.InFlightRequest
)
537 TdiSend(&FCB
->SendIrp
.InFlightRequest
,
538 FCB
->Connection
.Object
,
547 SocketStateUnlock(FCB
);
549 return STATUS_PENDING
;
553 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
554 PIO_STACK_LOCATION IrpSp
) {
555 NTSTATUS Status
= STATUS_SUCCESS
;
556 PTDI_CONNECTION_INFORMATION TargetAddress
;
557 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
558 PAFD_FCB FCB
= FileObject
->FsContext
;
559 PAFD_SEND_INFO_UDP SendReq
;
560 KPROCESSOR_MODE LockMode
;
562 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
564 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
566 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
568 /* Check that the socket is bound */
569 if( FCB
->State
!= SOCKET_STATE_BOUND
&&
570 FCB
->State
!= SOCKET_STATE_CREATED
)
572 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
573 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
578 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
579 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
582 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
583 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
585 if (FCB
->State
== SOCKET_STATE_CREATED
)
587 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
589 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
590 Address
[0].AddressType
);
592 if( FCB
->LocalAddress
) {
593 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
595 if( NT_SUCCESS(Status
) )
596 FCB
->State
= SOCKET_STATE_BOUND
;
598 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
600 return UnlockAndMaybeComplete
601 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
604 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
605 SendReq
->BufferCount
,
607 FALSE
, FALSE
, LockMode
);
609 if( !SendReq
->BufferArray
)
610 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
614 (MID_TRACE
,("RemoteAddress #%d Type %d\n",
615 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
617 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
618 Address
[0].AddressType
));
620 Status
= TdiBuildConnectionInfo( &TargetAddress
,
621 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
) );
623 /* Check the size of the Address given ... */
625 if( NT_SUCCESS(Status
) ) {
626 FCB
->PollState
&= ~AFD_EVENT_SEND
;
628 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
629 if (Status
== STATUS_PENDING
)
631 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
632 FCB
->AddressFile
.Object
,
633 SendReq
->BufferArray
[0].buf
,
634 SendReq
->BufferArray
[0].len
,
637 PacketSocketSendComplete
,
641 ExFreePool(TargetAddress
);
643 SocketStateUnlock(FCB
);
645 return STATUS_PENDING
;
649 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
650 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );