[CLT2012]
[reactos.git] / drivers / network / afd / afd / write.c
1 /*
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)
7 * UPDATE HISTORY:
8 * 20040708 Created
9 */
10 #include "afd.h"
11
12 static NTSTATUS NTAPI SendComplete
13 ( PDEVICE_OBJECT DeviceObject,
14 PIRP Irp,
15 PVOID Context ) {
16 NTSTATUS Status = Irp->IoStatus.Status;
17 PAFD_FCB FCB = (PAFD_FCB)Context;
18 PLIST_ENTRY NextIrpEntry;
19 PIRP NextIrp = NULL;
20 PIO_STACK_LOCATION NextIrpSp;
21 PAFD_SEND_INFO SendReq = NULL;
22 PAFD_MAPBUF Map;
23 UINT TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i;
24
25 /*
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
31 * processed).
32 */
33
34 AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
35 Irp->IoStatus.Status,
36 Irp->IoStatus.Information));
37
38 if( !SocketAcquireStateLock( FCB ) )
39 return STATUS_FILE_CLOSED;
40
41 ASSERT(FCB->SendIrp.InFlightRequest == Irp);
42 FCB->SendIrp.InFlightRequest = NULL;
43 /* Request is not in flight any longer */
44
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 );
58 }
59
60 RetryDisconnectCompletion(FCB);
61
62 SocketStateUnlock( FCB );
63 return STATUS_FILE_CLOSED;
64 }
65
66 if( !NT_SUCCESS(Status) ) {
67 /* Complete all following send IRPs with error */
68
69 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
70 NextIrpEntry =
71 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
72 NextIrp =
73 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
74 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
75 SendReq = GetLockedData(NextIrp, NextIrpSp);
76
77 UnlockBuffers( SendReq->BufferArray,
78 SendReq->BufferCount,
79 FALSE );
80
81 NextIrp->IoStatus.Status = Status;
82 NextIrp->IoStatus.Information = 0;
83
84 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
85 (void)IoSetCancelRoutine(NextIrp, NULL);
86 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
87 }
88
89 RetryDisconnectCompletion(FCB);
90
91 SocketStateUnlock( FCB );
92
93 return STATUS_SUCCESS;
94 }
95
96 RtlMoveMemory( FCB->Send.Window,
97 FCB->Send.Window + FCB->Send.BytesUsed,
98 FCB->Send.BytesUsed - Irp->IoStatus.Information );
99
100 TotalBytesProcessed = 0;
101 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) &&
102 TotalBytesProcessed != Irp->IoStatus.Information) {
103 NextIrpEntry =
104 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
105 NextIrp =
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);
110
111 TotalBytesCopied = 0;
112
113 for( i = 0; i < SendReq->BufferCount; i++ )
114 TotalBytesCopied += SendReq->BufferArray[i].len;
115
116 NextIrp->IoStatus.Status = Irp->IoStatus.Status;
117 NextIrp->IoStatus.Information = TotalBytesCopied;
118
119 TotalBytesProcessed += TotalBytesCopied;
120
121 (void)IoSetCancelRoutine(NextIrp, NULL);
122
123 UnlockBuffers( SendReq->BufferArray,
124 SendReq->BufferCount,
125 FALSE );
126
127 if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
128
129 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
130 }
131
132 ASSERT(TotalBytesProcessed == Irp->IoStatus.Information);
133
134 FCB->Send.BytesUsed -= TotalBytesProcessed;
135
136 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
137 NextIrpEntry =
138 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
139 NextIrp =
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);
144
145 AFD_DbgPrint(MID_TRACE,("SendReq @ %x\n", SendReq));
146
147 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
148 TotalBytesCopied = 0;
149
150 for( i = 0; i < SendReq->BufferCount; i++ ) {
151 if (SpaceAvail < SendReq->BufferArray[i].len)
152 {
153 InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND],
154 &NextIrp->Tail.Overlay.ListEntry);
155 NextIrp = NULL;
156 break;
157 }
158 Map[i].BufferAddress =
159 MmMapLockedPages( Map[i].Mdl, KernelMode );
160
161 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
162 Map[i].BufferAddress,
163 SendReq->BufferArray[i].len );
164
165 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
166
167 TotalBytesCopied += SendReq->BufferArray[i].len;
168 SpaceAvail -= SendReq->BufferArray[i].len;
169 }
170
171 if (NextIrp != NULL)
172 {
173 FCB->Send.BytesUsed += TotalBytesCopied;
174 }
175 else
176 break;
177 }
178
179 if (FCB->Send.Size - FCB->Send.BytesUsed != 0 &&
180 !FCB->SendClosed)
181 {
182 FCB->PollState |= AFD_EVENT_SEND;
183 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
184 PollReeval( FCB->DeviceExt, FCB->FileObject );
185 }
186 else
187 {
188 FCB->PollState &= ~AFD_EVENT_SEND;
189 }
190
191 /* Some data is still waiting */
192 if( FCB->Send.BytesUsed )
193 {
194 Status = TdiSend( &FCB->SendIrp.InFlightRequest,
195 FCB->Connection.Object,
196 0,
197 FCB->Send.Window,
198 FCB->Send.BytesUsed,
199 &FCB->SendIrp.Iosb,
200 SendComplete,
201 FCB );
202 }
203 else
204 {
205 /* Nothing is waiting so try to complete a pending disconnect */
206 RetryDisconnectCompletion(FCB);
207 }
208
209 SocketStateUnlock( FCB );
210
211 return STATUS_SUCCESS;
212 }
213
214 static NTSTATUS NTAPI PacketSocketSendComplete
215 ( PDEVICE_OBJECT DeviceObject,
216 PIRP Irp,
217 PVOID Context ) {
218 PAFD_FCB FCB = (PAFD_FCB)Context;
219 PLIST_ENTRY NextIrpEntry;
220 PIRP NextIrp;
221 PAFD_SEND_INFO SendReq;
222
223 AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
224 Irp->IoStatus.Status,
225 Irp->IoStatus.Information));
226
227 if( !SocketAcquireStateLock( FCB ) )
228 return STATUS_FILE_CLOSED;
229
230 ASSERT(FCB->SendIrp.InFlightRequest == Irp);
231 FCB->SendIrp.InFlightRequest = NULL;
232 /* Request is not in flight any longer */
233
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 );
246 }
247 SocketStateUnlock( FCB );
248 return STATUS_FILE_CLOSED;
249 }
250
251 ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
252
253 /* TDI spec guarantees FIFO ordering on IRPs */
254 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
255 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
256
257 SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
258
259 NextIrp->IoStatus.Status = Irp->IoStatus.Status;
260 NextIrp->IoStatus.Information = Irp->IoStatus.Information;
261
262 (void)IoSetCancelRoutine(NextIrp, NULL);
263
264 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
265
266 UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
267
268 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
269
270 FCB->PollState |= AFD_EVENT_SEND;
271 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
272 PollReeval(FCB->DeviceExt, FCB->FileObject);
273
274 SocketStateUnlock(FCB);
275
276 return STATUS_SUCCESS;
277 }
278
279 NTSTATUS NTAPI
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;
288
289 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
290
291 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
292
293 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
294 {
295 PAFD_SEND_INFO_UDP SendReq;
296 PTDI_CONNECTION_INFORMATION TargetAddress;
297
298 /* Check that the socket is bound */
299 if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress )
300 {
301 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
302 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp,
303 0 );
304 }
305
306 if( !(SendReq = LockRequest( Irp, IrpSp )) )
307 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 );
308
309 /* Must lock buffers before handing off user data */
310 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
311 SendReq->BufferCount,
312 NULL, NULL,
313 FALSE, FALSE );
314
315 if( !SendReq->BufferArray ) {
316 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
317 Irp, 0 );
318 }
319
320 Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
321
322 if( NT_SUCCESS(Status) ) {
323 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
324 FCB->PollState &= ~AFD_EVENT_SEND;
325
326 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
327 if (Status == STATUS_PENDING)
328 {
329 TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
330 FCB->AddressFile.Object,
331 SendReq->BufferArray[0].buf,
332 SendReq->BufferArray[0].len,
333 TargetAddress,
334 &FCB->SendIrp.Iosb,
335 PacketSocketSendComplete,
336 FCB);
337 }
338
339 ExFreePool( TargetAddress );
340
341 SocketStateUnlock(FCB);
342
343 return STATUS_PENDING;
344 }
345 else
346 {
347 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
348 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
349 }
350 }
351
352 if (FCB->PollState & AFD_EVENT_CLOSE)
353 {
354 AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n"));
355
356 /* This is an unexpected remote disconnect */
357 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
358 }
359
360 if (FCB->PollState & AFD_EVENT_ABORT)
361 {
362 AFD_DbgPrint(MIN_TRACE,("Connection aborted\n"));
363
364 /* This is an abortive socket closure on our side */
365 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
366 }
367
368 if (FCB->SendClosed)
369 {
370 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
371
372 /* This is a graceful send closure */
373 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
374 }
375
376 if( !(SendReq = LockRequest( Irp, IrpSp )) )
377 return UnlockAndMaybeComplete
378 ( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied );
379
380 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
381 SendReq->BufferCount,
382 NULL, NULL,
383 FALSE, FALSE );
384
385 if( !SendReq->BufferArray ) {
386 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
387 Irp, 0 );
388 }
389
390 AFD_DbgPrint(MID_TRACE,("Socket state %d\n", FCB->State));
391
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 );
398 } else {
399 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
400 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
401 }
402 }
403
404 AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n",
405 FCB->Send.BytesUsed));
406
407 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
408
409 AFD_DbgPrint(MID_TRACE,("We can accept %d bytes\n",
410 SpaceAvail));
411
412 for( i = 0; FCB->Send.BytesUsed < FCB->Send.Size &&
413 i < SendReq->BufferCount; i++ ) {
414
415 if (SpaceAvail < SendReq->BufferArray[i].len)
416 {
417 if (TotalBytesCopied + SendReq->BufferArray[i].len > FCB->Send.Size)
418 {
419 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
420
421 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_OVERFLOW, Irp, 0);
422 }
423 SpaceAvail += TotalBytesCopied;
424 NoSpace = TRUE;
425 break;
426 }
427
428 AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n",
429 i,
430 SendReq->BufferArray[i].buf,
431 SendReq->BufferArray[i].len,
432 FCB->Send.Window + FCB->Send.BytesUsed));
433
434 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
435 SendReq->BufferArray[i].buf,
436 SendReq->BufferArray[i].len );
437
438 TotalBytesCopied += SendReq->BufferArray[i].len;
439 SpaceAvail -= SendReq->BufferArray[i].len;
440 }
441
442 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
443
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 );
449 }
450
451 if (SpaceAvail)
452 {
453 FCB->PollState |= AFD_EVENT_SEND;
454 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
455 PollReeval( FCB->DeviceExt, FCB->FileObject );
456 }
457 else
458 {
459 FCB->PollState &= ~AFD_EVENT_SEND;
460 }
461
462 if (!NoSpace)
463 {
464 FCB->Send.BytesUsed += TotalBytesCopied;
465 AFD_DbgPrint(MID_TRACE,("Copied %d bytes\n", TotalBytesCopied));
466
467 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
468 if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest)
469 {
470 TdiSend(&FCB->SendIrp.InFlightRequest,
471 FCB->Connection.Object,
472 0,
473 FCB->Send.Window,
474 FCB->Send.BytesUsed,
475 &FCB->SendIrp.Iosb,
476 SendComplete,
477 FCB);
478 }
479 SocketStateUnlock(FCB);
480
481 return STATUS_PENDING;
482 }
483 else
484 {
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 );
491 } else {
492 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
493 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
494 }
495 }
496 }
497
498 NTSTATUS NTAPI
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;
506
507 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
508
509 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
510
511 /* Check that the socket is bound */
512 if( FCB->State != SOCKET_STATE_BOUND &&
513 FCB->State != SOCKET_STATE_CREATED)
514 {
515 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
516 return UnlockAndMaybeComplete
517 ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
518 }
519
520 if (FCB->SendClosed)
521 {
522 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
523 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
524 }
525
526 if( !(SendReq = LockRequest( Irp, IrpSp )) )
527 return UnlockAndMaybeComplete
528 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
529
530 if (FCB->State == SOCKET_STATE_CREATED)
531 {
532 if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress );
533 FCB->LocalAddress =
534 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
535 Address[0].AddressType );
536
537 if( FCB->LocalAddress ) {
538 Status = WarmSocketForBind( FCB );
539
540 if( NT_SUCCESS(Status) )
541 FCB->State = SOCKET_STATE_BOUND;
542 else
543 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
544 } else
545 return UnlockAndMaybeComplete
546 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
547 }
548
549 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
550 SendReq->BufferCount,
551 NULL, NULL,
552 FALSE, FALSE );
553
554 if( !SendReq->BufferArray )
555 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
556 Irp, 0 );
557
558 AFD_DbgPrint
559 (MID_TRACE,("RemoteAddress #%d Type %d\n",
560 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
561 TAAddressCount,
562 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
563 Address[0].AddressType));
564
565 Status = TdiBuildConnectionInfo( &TargetAddress,
566 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) );
567
568 /* Check the size of the Address given ... */
569
570 if( NT_SUCCESS(Status) ) {
571 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
572 FCB->PollState &= ~AFD_EVENT_SEND;
573
574 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
575 if (Status == STATUS_PENDING)
576 {
577 TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
578 FCB->AddressFile.Object,
579 SendReq->BufferArray[0].buf,
580 SendReq->BufferArray[0].len,
581 TargetAddress,
582 &FCB->SendIrp.Iosb,
583 PacketSocketSendComplete,
584 FCB);
585 }
586
587 ExFreePool( TargetAddress );
588
589 SocketStateUnlock(FCB);
590
591 return STATUS_PENDING;
592 }
593 else
594 {
595 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
596 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
597 }
598 }
599