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
;
26 * The Irp parameter passed in is the IRP of the stream between AFD and
27 * TDI driver. It's not very usefull to us. We need the IRPs of the stream
28 * between usermode and AFD. Those are chained from
29 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
30 * below as "NextIrp" ('cause they are the next usermode IRP to be
34 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
36 Irp
->IoStatus
.Information
));
38 if( !SocketAcquireStateLock( FCB
) )
39 return STATUS_FILE_CLOSED
;
41 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
42 FCB
->SendIrp
.InFlightRequest
= NULL
;
43 /* Request is not in flight any longer */
45 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
46 /* Cleanup our IRP queue because the FCB is being destroyed */
47 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
48 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
49 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
50 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
51 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
52 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
53 NextIrp
->IoStatus
.Information
= 0;
54 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
55 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
56 (void)IoSetCancelRoutine(NextIrp
, NULL
);
57 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
60 RetryDisconnectCompletion(FCB
);
62 SocketStateUnlock( FCB
);
63 return STATUS_FILE_CLOSED
;
66 if( !NT_SUCCESS(Status
) ) {
67 /* Complete all following send IRPs with error */
69 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
71 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
73 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
74 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
75 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
77 UnlockBuffers( SendReq
->BufferArray
,
81 NextIrp
->IoStatus
.Status
= Status
;
82 NextIrp
->IoStatus
.Information
= 0;
84 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
85 (void)IoSetCancelRoutine(NextIrp
, NULL
);
86 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
89 RetryDisconnectCompletion(FCB
);
91 SocketStateUnlock( FCB
);
93 return STATUS_SUCCESS
;
96 RtlMoveMemory( FCB
->Send
.Window
,
97 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
98 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
100 TotalBytesProcessed
= 0;
101 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) &&
102 TotalBytesProcessed
!= Irp
->IoStatus
.Information
) {
104 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
106 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
107 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
108 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
109 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
111 TotalBytesCopied
= 0;
113 for( i
= 0; i
< SendReq
->BufferCount
; i
++ )
114 TotalBytesCopied
+= SendReq
->BufferArray
[i
].len
;
116 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
117 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
119 TotalBytesProcessed
+= TotalBytesCopied
;
121 (void)IoSetCancelRoutine(NextIrp
, NULL
);
123 UnlockBuffers( SendReq
->BufferArray
,
124 SendReq
->BufferCount
,
127 if (NextIrp
->MdlAddress
) UnlockRequest(NextIrp
, NextIrpSp
);
129 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
132 ASSERT(TotalBytesProcessed
== Irp
->IoStatus
.Information
);
134 FCB
->Send
.BytesUsed
-= TotalBytesProcessed
;
136 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
138 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
140 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
141 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
142 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
143 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
145 AFD_DbgPrint(MID_TRACE
,("SendReq @ %x\n", SendReq
));
147 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
148 TotalBytesCopied
= 0;
150 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
151 if (SpaceAvail
< SendReq
->BufferArray
[i
].len
)
153 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
],
154 &NextIrp
->Tail
.Overlay
.ListEntry
);
158 Map
[i
].BufferAddress
=
159 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
161 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
162 Map
[i
].BufferAddress
,
163 SendReq
->BufferArray
[i
].len
);
165 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
167 TotalBytesCopied
+= SendReq
->BufferArray
[i
].len
;
168 SpaceAvail
-= SendReq
->BufferArray
[i
].len
;
173 FCB
->Send
.BytesUsed
+= TotalBytesCopied
;
179 if (FCB
->Send
.Size
- FCB
->Send
.BytesUsed
!= 0 &&
182 FCB
->PollState
|= AFD_EVENT_SEND
;
183 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
184 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
188 FCB
->PollState
&= ~AFD_EVENT_SEND
;
191 /* Some data is still waiting */
192 if( FCB
->Send
.BytesUsed
)
194 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
195 FCB
->Connection
.Object
,
205 /* Nothing is waiting so try to complete a pending disconnect */
206 RetryDisconnectCompletion(FCB
);
209 SocketStateUnlock( FCB
);
211 return STATUS_SUCCESS
;
214 static NTSTATUS NTAPI PacketSocketSendComplete
215 ( PDEVICE_OBJECT DeviceObject
,
218 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
219 PLIST_ENTRY NextIrpEntry
;
221 PAFD_SEND_INFO SendReq
;
223 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
224 Irp
->IoStatus
.Status
,
225 Irp
->IoStatus
.Information
));
227 if( !SocketAcquireStateLock( FCB
) )
228 return STATUS_FILE_CLOSED
;
230 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
231 FCB
->SendIrp
.InFlightRequest
= NULL
;
232 /* Request is not in flight any longer */
234 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
235 /* Cleanup our IRP queue because the FCB is being destroyed */
236 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
237 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
238 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
239 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
240 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
241 NextIrp
->IoStatus
.Information
= 0;
242 (void)IoSetCancelRoutine(NextIrp
, NULL
);
243 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
244 UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
245 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
247 SocketStateUnlock( FCB
);
248 return STATUS_FILE_CLOSED
;
251 ASSERT(!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]));
253 /* TDI spec guarantees FIFO ordering on IRPs */
254 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
255 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
257 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
259 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
260 NextIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
262 (void)IoSetCancelRoutine(NextIrp
, NULL
);
264 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
266 UnlockRequest(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
268 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
270 FCB
->PollState
|= AFD_EVENT_SEND
;
271 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
272 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
274 SocketStateUnlock(FCB
);
276 return STATUS_SUCCESS
;
280 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
281 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
282 NTSTATUS Status
= STATUS_SUCCESS
;
283 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
284 PAFD_FCB FCB
= FileObject
->FsContext
;
285 PAFD_SEND_INFO SendReq
;
286 UINT TotalBytesCopied
= 0, i
, SpaceAvail
= 0;
287 BOOLEAN NoSpace
= FALSE
;
289 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
291 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
293 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
295 PAFD_SEND_INFO_UDP SendReq
;
296 PTDI_CONNECTION_INFORMATION TargetAddress
;
298 /* Check that the socket is bound */
299 if( FCB
->State
!= SOCKET_STATE_BOUND
|| !FCB
->RemoteAddress
)
301 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
302 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
, Irp
,
306 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
307 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
309 /* Must lock buffers before handing off user data */
310 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
311 SendReq
->BufferCount
,
315 if( !SendReq
->BufferArray
) {
316 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
320 Status
= TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
322 if( NT_SUCCESS(Status
) ) {
323 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
324 FCB
->PollState
&= ~AFD_EVENT_SEND
;
326 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
327 if (Status
== STATUS_PENDING
)
329 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
330 FCB
->AddressFile
.Object
,
331 SendReq
->BufferArray
[0].buf
,
332 SendReq
->BufferArray
[0].len
,
335 PacketSocketSendComplete
,
339 ExFreePool( TargetAddress
);
341 SocketStateUnlock(FCB
);
343 return STATUS_PENDING
;
347 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
348 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
352 if (FCB
->PollState
& AFD_EVENT_CLOSE
)
354 AFD_DbgPrint(MIN_TRACE
,("Connection reset by remote peer\n"));
356 /* This is an unexpected remote disconnect */
357 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
360 if (FCB
->PollState
& AFD_EVENT_ABORT
)
362 AFD_DbgPrint(MIN_TRACE
,("Connection aborted\n"));
364 /* This is an abortive socket closure on our side */
365 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
370 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
372 /* This is a graceful send closure */
373 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
376 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
377 return UnlockAndMaybeComplete
378 ( FCB
, STATUS_NO_MEMORY
, Irp
, TotalBytesCopied
);
380 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
381 SendReq
->BufferCount
,
385 if( !SendReq
->BufferArray
) {
386 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
390 AFD_DbgPrint(MID_TRACE
,("Socket state %d\n", FCB
->State
));
392 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
393 if( (SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
) ) {
394 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
395 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
396 return UnlockAndMaybeComplete
397 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
399 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
400 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
404 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %d\n",
405 FCB
->Send
.BytesUsed
));
407 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
409 AFD_DbgPrint(MID_TRACE
,("We can accept %d bytes\n",
412 for( i
= 0; FCB
->Send
.BytesUsed
< FCB
->Send
.Size
&&
413 i
< SendReq
->BufferCount
; i
++ ) {
415 if (SpaceAvail
< SendReq
->BufferArray
[i
].len
)
417 if (TotalBytesCopied
+ SendReq
->BufferArray
[i
].len
> FCB
->Send
.Size
)
419 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
421 return UnlockAndMaybeComplete(FCB
, STATUS_BUFFER_OVERFLOW
, Irp
, 0);
423 SpaceAvail
+= TotalBytesCopied
;
428 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %d, %x:%d to %x\n",
430 SendReq
->BufferArray
[i
].buf
,
431 SendReq
->BufferArray
[i
].len
,
432 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
434 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
435 SendReq
->BufferArray
[i
].buf
,
436 SendReq
->BufferArray
[i
].len
);
438 TotalBytesCopied
+= SendReq
->BufferArray
[i
].len
;
439 SpaceAvail
-= SendReq
->BufferArray
[i
].len
;
442 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
444 if( TotalBytesCopied
== 0 ) {
445 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
446 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
447 return UnlockAndMaybeComplete
448 ( FCB
, STATUS_SUCCESS
, Irp
, TotalBytesCopied
);
453 FCB
->PollState
|= AFD_EVENT_SEND
;
454 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
455 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
459 FCB
->PollState
&= ~AFD_EVENT_SEND
;
464 FCB
->Send
.BytesUsed
+= TotalBytesCopied
;
465 AFD_DbgPrint(MID_TRACE
,("Copied %d bytes\n", TotalBytesCopied
));
467 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
468 if (Status
== STATUS_PENDING
&& !FCB
->SendIrp
.InFlightRequest
)
470 TdiSend(&FCB
->SendIrp
.InFlightRequest
,
471 FCB
->Connection
.Object
,
479 SocketStateUnlock(FCB
);
481 return STATUS_PENDING
;
485 FCB
->PollState
&= ~AFD_EVENT_SEND
;
486 if( (SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
) ) {
487 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
488 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
489 return UnlockAndMaybeComplete
490 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
492 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
493 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
499 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
500 PIO_STACK_LOCATION IrpSp
) {
501 NTSTATUS Status
= STATUS_SUCCESS
;
502 PTDI_CONNECTION_INFORMATION TargetAddress
;
503 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
504 PAFD_FCB FCB
= FileObject
->FsContext
;
505 PAFD_SEND_INFO_UDP SendReq
;
507 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
509 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
511 /* Check that the socket is bound */
512 if( FCB
->State
!= SOCKET_STATE_BOUND
&&
513 FCB
->State
!= SOCKET_STATE_CREATED
)
515 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
516 return UnlockAndMaybeComplete
517 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0 );
522 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
523 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
526 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
527 return UnlockAndMaybeComplete
528 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
530 if (FCB
->State
== SOCKET_STATE_CREATED
)
532 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
534 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
535 Address
[0].AddressType
);
537 if( FCB
->LocalAddress
) {
538 Status
= WarmSocketForBind( FCB
);
540 if( NT_SUCCESS(Status
) )
541 FCB
->State
= SOCKET_STATE_BOUND
;
543 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
545 return UnlockAndMaybeComplete
546 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
549 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
550 SendReq
->BufferCount
,
554 if( !SendReq
->BufferArray
)
555 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
559 (MID_TRACE
,("RemoteAddress #%d Type %d\n",
560 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
562 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
563 Address
[0].AddressType
));
565 Status
= TdiBuildConnectionInfo( &TargetAddress
,
566 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
) );
568 /* Check the size of the Address given ... */
570 if( NT_SUCCESS(Status
) ) {
571 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
572 FCB
->PollState
&= ~AFD_EVENT_SEND
;
574 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
575 if (Status
== STATUS_PENDING
)
577 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
578 FCB
->AddressFile
.Object
,
579 SendReq
->BufferArray
[0].buf
,
580 SendReq
->BufferArray
[0].len
,
583 PacketSocketSendComplete
,
587 ExFreePool( TargetAddress
);
589 SocketStateUnlock(FCB
);
591 return STATUS_PENDING
;
595 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
596 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );