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