Sync with trunk r65656.
[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
11 #include "afd.h"
12
13 static IO_COMPLETION_ROUTINE SendComplete;
14 static NTSTATUS NTAPI SendComplete
15 ( PDEVICE_OBJECT DeviceObject,
16 PIRP Irp,
17 PVOID Context ) {
18 NTSTATUS Status = Irp->IoStatus.Status;
19 PAFD_FCB FCB = (PAFD_FCB)Context;
20 PLIST_ENTRY NextIrpEntry;
21 PIRP NextIrp = NULL;
22 PIO_STACK_LOCATION NextIrpSp;
23 PAFD_SEND_INFO SendReq = NULL;
24 PAFD_MAPBUF Map;
25 UINT TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i;
26 UINT SendLength, BytesCopied;
27 BOOLEAN HaltSendQueue;
28
29 UNREFERENCED_PARAMETER(DeviceObject);
30
31 /*
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
37 * processed).
38 */
39
40 AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n",
41 Irp->IoStatus.Status,
42 Irp->IoStatus.Information));
43
44 if( !SocketAcquireStateLock( FCB ) )
45 return STATUS_FILE_CLOSED;
46
47 ASSERT(FCB->SendIrp.InFlightRequest == Irp);
48 FCB->SendIrp.InFlightRequest = NULL;
49 /* Request is not in flight any longer */
50
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 );
64 }
65
66 RetryDisconnectCompletion(FCB);
67
68 SocketStateUnlock( FCB );
69 return STATUS_FILE_CLOSED;
70 }
71
72 if( !NT_SUCCESS(Status) ) {
73 /* Complete all following send IRPs with error */
74
75 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
76 NextIrpEntry =
77 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
78 NextIrp =
79 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
80 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
81 SendReq = GetLockedData(NextIrp, NextIrpSp);
82
83 UnlockBuffers( SendReq->BufferArray,
84 SendReq->BufferCount,
85 FALSE );
86
87 NextIrp->IoStatus.Status = Status;
88 NextIrp->IoStatus.Information = 0;
89
90 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
91 (void)IoSetCancelRoutine(NextIrp, NULL);
92 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
93 }
94
95 RetryDisconnectCompletion(FCB);
96
97 SocketStateUnlock( FCB );
98
99 return STATUS_SUCCESS;
100 }
101
102 RtlMoveMemory( FCB->Send.Window,
103 FCB->Send.Window + Irp->IoStatus.Information,
104 FCB->Send.BytesUsed - Irp->IoStatus.Information );
105
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);
115
116 TotalBytesCopied = (ULONG_PTR)NextIrp->Tail.Overlay.DriverContext[3];
117 ASSERT(TotalBytesCopied != 0);
118
119 /* If we didn't get enough, keep waiting */
120 if (TotalBytesCopied > SendLength)
121 {
122 /* Update the bytes left to copy */
123 TotalBytesCopied -= SendLength;
124 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)TotalBytesCopied;
125
126 /* Update the state variables */
127 FCB->Send.BytesUsed -= SendLength;
128 TotalBytesProcessed += SendLength;
129 SendLength = 0;
130
131 /* Pend the IRP */
132 InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND],
133 &NextIrp->Tail.Overlay.ListEntry);
134 HaltSendQueue = TRUE;
135 break;
136 }
137
138 ASSERT(NextIrp->IoStatus.Information != 0);
139
140 NextIrp->IoStatus.Status = Irp->IoStatus.Status;
141
142 FCB->Send.BytesUsed -= TotalBytesCopied;
143 TotalBytesProcessed += TotalBytesCopied;
144 SendLength -= TotalBytesCopied;
145
146 (void)IoSetCancelRoutine(NextIrp, NULL);
147
148 UnlockBuffers( SendReq->BufferArray,
149 SendReq->BufferCount,
150 FALSE );
151
152 if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
153
154 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
155 }
156
157 ASSERT(SendLength == 0);
158
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);
165
166 AFD_DbgPrint(MID_TRACE,("SendReq @ %p\n", SendReq));
167
168 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
169 TotalBytesCopied = 0;
170
171 /* Count the total transfer size */
172 SendLength = 0;
173 for (i = 0; i < SendReq->BufferCount; i++)
174 {
175 SendLength += SendReq->BufferArray[i].len;
176 }
177
178 /* Make sure we've got the space */
179 if (SendLength > SpaceAvail)
180 {
181 /* Blocking sockets have to wait here */
182 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
183 {
184 FCB->PollState &= ~AFD_EVENT_SEND;
185
186 NextIrp = NULL;
187 }
188
189 /* Check if we can send anything */
190 if (SpaceAvail == 0)
191 {
192 FCB->PollState &= ~AFD_EVENT_SEND;
193
194 /* We should never be non-overlapped and get to this point */
195 ASSERT(SendReq->AfdFlags & AFD_OVERLAPPED);
196
197 NextIrp = NULL;
198 }
199 }
200
201 if (NextIrp != NULL)
202 {
203 for( i = 0; i < SendReq->BufferCount; i++ ) {
204 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail);
205
206 Map[i].BufferAddress =
207 MmMapLockedPages( Map[i].Mdl, KernelMode );
208
209 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
210 Map[i].BufferAddress,
211 BytesCopied );
212
213 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
214
215 TotalBytesCopied += BytesCopied;
216 SpaceAvail -= BytesCopied;
217 FCB->Send.BytesUsed += BytesCopied;
218 }
219
220 NextIrp->IoStatus.Information = TotalBytesCopied;
221 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)NextIrp->IoStatus.Information;
222 }
223 }
224
225 if (FCB->Send.Size - FCB->Send.BytesUsed != 0 && !FCB->SendClosed &&
226 IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]))
227 {
228 FCB->PollState |= AFD_EVENT_SEND;
229 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
230 PollReeval( FCB->DeviceExt, FCB->FileObject );
231 }
232 else
233 {
234 FCB->PollState &= ~AFD_EVENT_SEND;
235 }
236
237
238 /* Some data is still waiting */
239 if( FCB->Send.BytesUsed )
240 {
241 Status = TdiSend( &FCB->SendIrp.InFlightRequest,
242 FCB->Connection.Object,
243 0,
244 FCB->Send.Window,
245 FCB->Send.BytesUsed,
246 SendComplete,
247 FCB );
248 }
249 else
250 {
251 /* Nothing is waiting so try to complete a pending disconnect */
252 RetryDisconnectCompletion(FCB);
253 }
254
255 SocketStateUnlock( FCB );
256
257 return STATUS_SUCCESS;
258 }
259
260 static IO_COMPLETION_ROUTINE PacketSocketSendComplete;
261 static NTSTATUS NTAPI PacketSocketSendComplete
262 ( PDEVICE_OBJECT DeviceObject,
263 PIRP Irp,
264 PVOID Context ) {
265 PAFD_FCB FCB = (PAFD_FCB)Context;
266 PLIST_ENTRY NextIrpEntry;
267 PIRP NextIrp;
268 PAFD_SEND_INFO SendReq;
269
270 UNREFERENCED_PARAMETER(DeviceObject);
271
272 AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n",
273 Irp->IoStatus.Status,
274 Irp->IoStatus.Information));
275
276 if( !SocketAcquireStateLock( FCB ) )
277 return STATUS_FILE_CLOSED;
278
279 ASSERT(FCB->SendIrp.InFlightRequest == Irp);
280 FCB->SendIrp.InFlightRequest = NULL;
281 /* Request is not in flight any longer */
282
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 );
295 }
296 SocketStateUnlock( FCB );
297 return STATUS_FILE_CLOSED;
298 }
299
300 ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
301
302 /* TDI spec guarantees FIFO ordering on IRPs */
303 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
304 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
305
306 SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
307
308 NextIrp->IoStatus.Status = Irp->IoStatus.Status;
309 NextIrp->IoStatus.Information = Irp->IoStatus.Information;
310
311 (void)IoSetCancelRoutine(NextIrp, NULL);
312
313 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
314
315 UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
316
317 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
318
319 FCB->PollState |= AFD_EVENT_SEND;
320 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
321 PollReeval(FCB->DeviceExt, FCB->FileObject);
322
323 SocketStateUnlock(FCB);
324
325 return STATUS_SUCCESS;
326 }
327
328 NTSTATUS NTAPI
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;
337
338 UNREFERENCED_PARAMETER(DeviceObject);
339 UNREFERENCED_PARAMETER(Short);
340
341 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
342
343 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
344
345 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
346
347 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
348 {
349 PAFD_SEND_INFO_UDP SendReq;
350 PTDI_CONNECTION_INFORMATION TargetAddress;
351
352 /* Check that the socket is bound */
353 if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress )
354 {
355 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
356 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp,
357 0 );
358 }
359
360 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
361 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 );
362
363 /* Must lock buffers before handing off user data */
364 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
365 SendReq->BufferCount,
366 NULL, NULL,
367 FALSE, FALSE, LockMode );
368
369 if( !SendReq->BufferArray ) {
370 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
371 Irp, 0 );
372 }
373
374 Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
375
376 if( NT_SUCCESS(Status) ) {
377 FCB->PollState &= ~AFD_EVENT_SEND;
378
379 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
380 if (Status == STATUS_PENDING)
381 {
382 TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
383 FCB->AddressFile.Object,
384 SendReq->BufferArray[0].buf,
385 SendReq->BufferArray[0].len,
386 TargetAddress,
387 PacketSocketSendComplete,
388 FCB);
389 }
390
391 ExFreePool( TargetAddress );
392
393 SocketStateUnlock(FCB);
394
395 return STATUS_PENDING;
396 }
397 else
398 {
399 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
400 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
401 }
402 }
403
404 if (FCB->PollState & AFD_EVENT_CLOSE)
405 {
406 AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n"));
407
408 /* This is an unexpected remote disconnect */
409 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
410 }
411
412 if (FCB->PollState & AFD_EVENT_ABORT)
413 {
414 AFD_DbgPrint(MIN_TRACE,("Connection aborted\n"));
415
416 /* This is an abortive socket closure on our side */
417 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
418 }
419
420 if (FCB->SendClosed)
421 {
422 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
423
424 /* This is a graceful send closure */
425 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
426 }
427
428 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
429 return UnlockAndMaybeComplete
430 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
431
432 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
433 SendReq->BufferCount,
434 NULL, NULL,
435 FALSE, FALSE, LockMode );
436
437 if( !SendReq->BufferArray ) {
438 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
439 Irp, 0 );
440 }
441
442 AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State));
443
444 if( FCB->State != SOCKET_STATE_CONNECTED ) {
445 if (!(SendReq->AfdFlags & AFD_OVERLAPPED) &&
446 ((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
447 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
448 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
449 return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 );
450 } else {
451 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
452 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
453 }
454 }
455
456 AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n",
457 FCB->Send.BytesUsed));
458
459 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
460
461 AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n",
462 SpaceAvail));
463
464 /* Count the total transfer size */
465 SendLength = 0;
466 for (i = 0; i < SendReq->BufferCount; i++)
467 {
468 SendLength += SendReq->BufferArray[i].len;
469 }
470
471 /* Make sure we've got the space */
472 if (SendLength > SpaceAvail)
473 {
474 /* Blocking sockets have to wait here */
475 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
476 {
477 FCB->PollState &= ~AFD_EVENT_SEND;
478 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
479 }
480
481 /* Check if we can send anything */
482 if (SpaceAvail == 0)
483 {
484 FCB->PollState &= ~AFD_EVENT_SEND;
485
486 /* Non-overlapped sockets will fail if we can send nothing */
487 if (!(SendReq->AfdFlags & AFD_OVERLAPPED))
488 {
489 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
490 return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 );
491 }
492 else
493 {
494 /* Overlapped sockets just pend */
495 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
496 }
497 }
498 }
499
500 for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ )
501 {
502 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail);
503
504 AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n",
505 i,
506 SendReq->BufferArray[i].buf,
507 BytesCopied,
508 FCB->Send.Window + FCB->Send.BytesUsed));
509
510 RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed,
511 SendReq->BufferArray[i].buf,
512 BytesCopied);
513
514 TotalBytesCopied += BytesCopied;
515 SpaceAvail -= BytesCopied;
516 FCB->Send.BytesUsed += BytesCopied;
517 }
518
519 Irp->IoStatus.Information = TotalBytesCopied;
520
521 if( TotalBytesCopied == 0 ) {
522 AFD_DbgPrint(MID_TRACE,("Empty send\n"));
523 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
524 return UnlockAndMaybeComplete
525 ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied );
526 }
527
528 if (SpaceAvail)
529 {
530 FCB->PollState |= AFD_EVENT_SEND;
531 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
532 PollReeval( FCB->DeviceExt, FCB->FileObject );
533 }
534 else
535 {
536 FCB->PollState &= ~AFD_EVENT_SEND;
537 }
538
539 /* We use the IRP tail for some temporary storage here */
540 Irp->Tail.Overlay.DriverContext[3] = (PVOID)Irp->IoStatus.Information;
541
542 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
543 if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest)
544 {
545 TdiSend(&FCB->SendIrp.InFlightRequest,
546 FCB->Connection.Object,
547 0,
548 FCB->Send.Window,
549 FCB->Send.BytesUsed,
550 SendComplete,
551 FCB);
552 }
553
554 SocketStateUnlock(FCB);
555
556 return STATUS_PENDING;
557 }
558
559 NTSTATUS NTAPI
560 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
561 PIO_STACK_LOCATION IrpSp) {
562 NTSTATUS Status = STATUS_SUCCESS;
563 PTDI_CONNECTION_INFORMATION TargetAddress;
564 PFILE_OBJECT FileObject = IrpSp->FileObject;
565 PAFD_FCB FCB = FileObject->FsContext;
566 PAFD_SEND_INFO_UDP SendReq;
567 KPROCESSOR_MODE LockMode;
568
569 UNREFERENCED_PARAMETER(DeviceObject);
570
571 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
572
573 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
574
575 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
576
577 /* Check that the socket is bound */
578 if( FCB->State != SOCKET_STATE_BOUND &&
579 FCB->State != SOCKET_STATE_CREATED)
580 {
581 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
582 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
583 }
584
585 if (FCB->SendClosed)
586 {
587 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
588 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
589 }
590
591 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
592 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
593
594 if (FCB->State == SOCKET_STATE_CREATED)
595 {
596 if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress );
597 FCB->LocalAddress =
598 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
599 Address[0].AddressType );
600
601 if( FCB->LocalAddress ) {
602 Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD );
603
604 if( NT_SUCCESS(Status) )
605 FCB->State = SOCKET_STATE_BOUND;
606 else
607 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
608 } else
609 return UnlockAndMaybeComplete
610 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
611 }
612
613 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
614 SendReq->BufferCount,
615 NULL, NULL,
616 FALSE, FALSE, LockMode );
617
618 if( !SendReq->BufferArray )
619 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
620 Irp, 0 );
621
622 AFD_DbgPrint
623 (MID_TRACE,("RemoteAddress #%d Type %u\n",
624 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
625 TAAddressCount,
626 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
627 Address[0].AddressType));
628
629 Status = TdiBuildConnectionInfo( &TargetAddress,
630 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) );
631
632 /* Check the size of the Address given ... */
633
634 if( NT_SUCCESS(Status) ) {
635 FCB->PollState &= ~AFD_EVENT_SEND;
636
637 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
638 if (Status == STATUS_PENDING)
639 {
640 TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
641 FCB->AddressFile.Object,
642 SendReq->BufferArray[0].buf,
643 SendReq->BufferArray[0].len,
644 TargetAddress,
645 PacketSocketSendComplete,
646 FCB);
647 }
648
649 ExFreePool(TargetAddress);
650
651 SocketStateUnlock(FCB);
652
653 return STATUS_PENDING;
654 }
655 else
656 {
657 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
658 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
659 }
660 }