Sunc with trunk revision 58971.
[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 IO_COMPLETION_ROUTINE SendComplete;
13 static NTSTATUS NTAPI SendComplete
14 ( PDEVICE_OBJECT DeviceObject,
15 PIRP Irp,
16 PVOID Context ) {
17 NTSTATUS Status = Irp->IoStatus.Status;
18 PAFD_FCB FCB = (PAFD_FCB)Context;
19 PLIST_ENTRY NextIrpEntry;
20 PIRP NextIrp = NULL;
21 PIO_STACK_LOCATION NextIrpSp;
22 PAFD_SEND_INFO SendReq = NULL;
23 PAFD_MAPBUF Map;
24 UINT TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i;
25 UINT SendLength, BytesCopied;
26 BOOLEAN HaltSendQueue;
27
28 UNREFERENCED_PARAMETER(DeviceObject);
29
30 /*
31 * The Irp parameter passed in is the IRP of the stream between AFD and
32 * TDI driver. It's not very usefull to us. We need the IRPs of the stream
33 * between usermode and AFD. Those are chained from
34 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
35 * below as "NextIrp" ('cause they are the next usermode IRP to be
36 * processed).
37 */
38
39 AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n",
40 Irp->IoStatus.Status,
41 Irp->IoStatus.Information));
42
43 if( !SocketAcquireStateLock( FCB ) )
44 return STATUS_FILE_CLOSED;
45
46 ASSERT(FCB->SendIrp.InFlightRequest == Irp);
47 FCB->SendIrp.InFlightRequest = NULL;
48 /* Request is not in flight any longer */
49
50 if( FCB->State == SOCKET_STATE_CLOSED ) {
51 /* Cleanup our IRP queue because the FCB is being destroyed */
52 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
53 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
54 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
55 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
56 SendReq = GetLockedData(NextIrp, NextIrpSp);
57 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
58 NextIrp->IoStatus.Information = 0;
59 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
60 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
61 (void)IoSetCancelRoutine(NextIrp, NULL);
62 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
63 }
64
65 RetryDisconnectCompletion(FCB);
66
67 SocketStateUnlock( FCB );
68 return STATUS_FILE_CLOSED;
69 }
70
71 if( !NT_SUCCESS(Status) ) {
72 /* Complete all following send IRPs with error */
73
74 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
75 NextIrpEntry =
76 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
77 NextIrp =
78 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
79 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
80 SendReq = GetLockedData(NextIrp, NextIrpSp);
81
82 UnlockBuffers( SendReq->BufferArray,
83 SendReq->BufferCount,
84 FALSE );
85
86 NextIrp->IoStatus.Status = Status;
87 NextIrp->IoStatus.Information = 0;
88
89 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
90 (void)IoSetCancelRoutine(NextIrp, NULL);
91 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
92 }
93
94 RetryDisconnectCompletion(FCB);
95
96 SocketStateUnlock( FCB );
97
98 return STATUS_SUCCESS;
99 }
100
101 RtlMoveMemory( FCB->Send.Window,
102 FCB->Send.Window + Irp->IoStatus.Information,
103 FCB->Send.BytesUsed - Irp->IoStatus.Information );
104
105 TotalBytesProcessed = 0;
106 SendLength = Irp->IoStatus.Information;
107 HaltSendQueue = FALSE;
108 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && SendLength > 0) {
109 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
110 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
111 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
112 SendReq = GetLockedData(NextIrp, NextIrpSp);
113 Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
114
115 TotalBytesCopied = (ULONG_PTR)NextIrp->Tail.Overlay.DriverContext[3];
116 ASSERT(TotalBytesCopied != 0);
117
118 /* If we didn't get enough, keep waiting */
119 if (TotalBytesCopied > SendLength)
120 {
121 /* Update the bytes left to copy */
122 TotalBytesCopied -= SendLength;
123 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)TotalBytesCopied;
124
125 /* Update the state variables */
126 FCB->Send.BytesUsed -= SendLength;
127 TotalBytesProcessed += SendLength;
128 SendLength = 0;
129
130 /* Pend the IRP */
131 InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND],
132 &NextIrp->Tail.Overlay.ListEntry);
133 HaltSendQueue = TRUE;
134 break;
135 }
136
137 ASSERT(NextIrp->IoStatus.Information != 0);
138
139 NextIrp->IoStatus.Status = Irp->IoStatus.Status;
140
141 FCB->Send.BytesUsed -= TotalBytesCopied;
142 TotalBytesProcessed += TotalBytesCopied;
143 SendLength -= TotalBytesCopied;
144
145 (void)IoSetCancelRoutine(NextIrp, NULL);
146
147 UnlockBuffers( SendReq->BufferArray,
148 SendReq->BufferCount,
149 FALSE );
150
151 if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
152
153 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
154 }
155
156 ASSERT(SendLength == 0);
157
158 if ( !HaltSendQueue && !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
159 NextIrpEntry = FCB->PendingIrpList[FUNCTION_SEND].Flink;
160 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
161 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
162 SendReq = GetLockedData(NextIrp, NextIrpSp);
163 Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
164
165 AFD_DbgPrint(MID_TRACE,("SendReq @ %p\n", SendReq));
166
167 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
168 TotalBytesCopied = 0;
169
170 /* Count the total transfer size */
171 SendLength = 0;
172 for (i = 0; i < SendReq->BufferCount; i++)
173 {
174 SendLength += SendReq->BufferArray[i].len;
175 }
176
177 /* Make sure we've got the space */
178 if (SendLength > SpaceAvail)
179 {
180 /* Blocking sockets have to wait here */
181 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
182 {
183 FCB->PollState &= ~AFD_EVENT_SEND;
184
185 NextIrp = NULL;
186 }
187
188 /* Check if we can send anything */
189 if (SpaceAvail == 0)
190 {
191 FCB->PollState &= ~AFD_EVENT_SEND;
192
193 /* We should never be non-overlapped and get to this point */
194 ASSERT(SendReq->AfdFlags & AFD_OVERLAPPED);
195
196 NextIrp = NULL;
197 }
198 }
199
200 if (NextIrp != NULL)
201 {
202 for( i = 0; i < SendReq->BufferCount; i++ ) {
203 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail);
204
205 Map[i].BufferAddress =
206 MmMapLockedPages( Map[i].Mdl, KernelMode );
207
208 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
209 Map[i].BufferAddress,
210 BytesCopied );
211
212 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
213
214 TotalBytesCopied += BytesCopied;
215 SpaceAvail -= BytesCopied;
216 FCB->Send.BytesUsed += BytesCopied;
217 }
218
219 NextIrp->IoStatus.Information = TotalBytesCopied;
220 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)NextIrp->IoStatus.Information;
221 }
222 }
223
224 if (FCB->Send.Size - FCB->Send.BytesUsed != 0 && !FCB->SendClosed &&
225 IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]))
226 {
227 FCB->PollState |= AFD_EVENT_SEND;
228 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
229 PollReeval( FCB->DeviceExt, FCB->FileObject );
230 }
231 else
232 {
233 FCB->PollState &= ~AFD_EVENT_SEND;
234 }
235
236
237 /* Some data is still waiting */
238 if( FCB->Send.BytesUsed )
239 {
240 Status = TdiSend( &FCB->SendIrp.InFlightRequest,
241 FCB->Connection.Object,
242 0,
243 FCB->Send.Window,
244 FCB->Send.BytesUsed,
245 &FCB->SendIrp.Iosb,
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 &FCB->SendIrp.Iosb,
388 PacketSocketSendComplete,
389 FCB);
390 }
391
392 ExFreePool( TargetAddress );
393
394 SocketStateUnlock(FCB);
395
396 return STATUS_PENDING;
397 }
398 else
399 {
400 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
401 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
402 }
403 }
404
405 if (FCB->PollState & AFD_EVENT_CLOSE)
406 {
407 AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n"));
408
409 /* This is an unexpected remote disconnect */
410 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
411 }
412
413 if (FCB->PollState & AFD_EVENT_ABORT)
414 {
415 AFD_DbgPrint(MIN_TRACE,("Connection aborted\n"));
416
417 /* This is an abortive socket closure on our side */
418 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
419 }
420
421 if (FCB->SendClosed)
422 {
423 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
424
425 /* This is a graceful send closure */
426 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
427 }
428
429 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
430 return UnlockAndMaybeComplete
431 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
432
433 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
434 SendReq->BufferCount,
435 NULL, NULL,
436 FALSE, FALSE, LockMode );
437
438 if( !SendReq->BufferArray ) {
439 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
440 Irp, 0 );
441 }
442
443 AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State));
444
445 if( FCB->State != SOCKET_STATE_CONNECTED ) {
446 if (!(SendReq->AfdFlags & AFD_OVERLAPPED) &&
447 ((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
448 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
449 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
450 return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 );
451 } else {
452 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
453 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
454 }
455 }
456
457 AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n",
458 FCB->Send.BytesUsed));
459
460 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
461
462 AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n",
463 SpaceAvail));
464
465 /* Count the total transfer size */
466 SendLength = 0;
467 for (i = 0; i < SendReq->BufferCount; i++)
468 {
469 SendLength += SendReq->BufferArray[i].len;
470 }
471
472 /* Make sure we've got the space */
473 if (SendLength > SpaceAvail)
474 {
475 /* Blocking sockets have to wait here */
476 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
477 {
478 FCB->PollState &= ~AFD_EVENT_SEND;
479 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
480 }
481
482 /* Check if we can send anything */
483 if (SpaceAvail == 0)
484 {
485 FCB->PollState &= ~AFD_EVENT_SEND;
486
487 /* Non-overlapped sockets will fail if we can send nothing */
488 if (!(SendReq->AfdFlags & AFD_OVERLAPPED))
489 {
490 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
491 return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 );
492 }
493 else
494 {
495 /* Overlapped sockets just pend */
496 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
497 }
498 }
499 }
500
501 for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ )
502 {
503 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail);
504
505 AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n",
506 i,
507 SendReq->BufferArray[i].buf,
508 BytesCopied,
509 FCB->Send.Window + FCB->Send.BytesUsed));
510
511 RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed,
512 SendReq->BufferArray[i].buf,
513 BytesCopied);
514
515 TotalBytesCopied += BytesCopied;
516 SpaceAvail -= BytesCopied;
517 FCB->Send.BytesUsed += BytesCopied;
518 }
519
520 Irp->IoStatus.Information = TotalBytesCopied;
521
522 if( TotalBytesCopied == 0 ) {
523 AFD_DbgPrint(MID_TRACE,("Empty send\n"));
524 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
525 return UnlockAndMaybeComplete
526 ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied );
527 }
528
529 if (SpaceAvail)
530 {
531 FCB->PollState |= AFD_EVENT_SEND;
532 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
533 PollReeval( FCB->DeviceExt, FCB->FileObject );
534 }
535 else
536 {
537 FCB->PollState &= ~AFD_EVENT_SEND;
538 }
539
540 /* We use the IRP tail for some temporary storage here */
541 Irp->Tail.Overlay.DriverContext[3] = (PVOID)Irp->IoStatus.Information;
542
543 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
544 if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest)
545 {
546 TdiSend(&FCB->SendIrp.InFlightRequest,
547 FCB->Connection.Object,
548 0,
549 FCB->Send.Window,
550 FCB->Send.BytesUsed,
551 &FCB->SendIrp.Iosb,
552 SendComplete,
553 FCB);
554 }
555
556 SocketStateUnlock(FCB);
557
558 return STATUS_PENDING;
559 }
560
561 NTSTATUS NTAPI
562 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
563 PIO_STACK_LOCATION IrpSp) {
564 NTSTATUS Status = STATUS_SUCCESS;
565 PTDI_CONNECTION_INFORMATION TargetAddress;
566 PFILE_OBJECT FileObject = IrpSp->FileObject;
567 PAFD_FCB FCB = FileObject->FsContext;
568 PAFD_SEND_INFO_UDP SendReq;
569 KPROCESSOR_MODE LockMode;
570
571 UNREFERENCED_PARAMETER(DeviceObject);
572
573 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
574
575 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
576
577 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
578
579 /* Check that the socket is bound */
580 if( FCB->State != SOCKET_STATE_BOUND &&
581 FCB->State != SOCKET_STATE_CREATED)
582 {
583 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
584 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
585 }
586
587 if (FCB->SendClosed)
588 {
589 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
590 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
591 }
592
593 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
594 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
595
596 if (FCB->State == SOCKET_STATE_CREATED)
597 {
598 if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress );
599 FCB->LocalAddress =
600 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
601 Address[0].AddressType );
602
603 if( FCB->LocalAddress ) {
604 Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD );
605
606 if( NT_SUCCESS(Status) )
607 FCB->State = SOCKET_STATE_BOUND;
608 else
609 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
610 } else
611 return UnlockAndMaybeComplete
612 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
613 }
614
615 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
616 SendReq->BufferCount,
617 NULL, NULL,
618 FALSE, FALSE, LockMode );
619
620 if( !SendReq->BufferArray )
621 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
622 Irp, 0 );
623
624 AFD_DbgPrint
625 (MID_TRACE,("RemoteAddress #%d Type %u\n",
626 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
627 TAAddressCount,
628 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
629 Address[0].AddressType));
630
631 Status = TdiBuildConnectionInfo( &TargetAddress,
632 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) );
633
634 /* Check the size of the Address given ... */
635
636 if( NT_SUCCESS(Status) ) {
637 FCB->PollState &= ~AFD_EVENT_SEND;
638
639 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
640 if (Status == STATUS_PENDING)
641 {
642 TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
643 FCB->AddressFile.Object,
644 SendReq->BufferArray[0].buf,
645 SendReq->BufferArray[0].len,
646 TargetAddress,
647 &FCB->SendIrp.Iosb,
648 PacketSocketSendComplete,
649 FCB);
650 }
651
652 ExFreePool(TargetAddress);
653
654 SocketStateUnlock(FCB);
655
656 return STATUS_PENDING;
657 }
658 else
659 {
660 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
661 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
662 }
663 }
664