xref: /reactos/drivers/network/afd/afd/write.c (revision 9e066abe)
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;
SendComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)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     SIZE_T 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 useful 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;
PacketSocketSendComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)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
AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp,BOOLEAN Short)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                 Status = 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                 if (Status != STATUS_PENDING)
390                 {
391                     NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry);
392                     Irp->IoStatus.Status = Status;
393                     Irp->IoStatus.Information = 0;
394                     (void)IoSetCancelRoutine(Irp, NULL);
395                     UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
396                     UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp));
397                     IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
398                 }
399             }
400 
401             ExFreePoolWithTag(TargetAddress, TAG_AFD_TDI_CONNECTION_INFORMATION);
402 
403             SocketStateUnlock(FCB);
404 
405             return STATUS_PENDING;
406         }
407         else
408         {
409             UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
410             return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
411         }
412     }
413 
414     if (FCB->PollState & AFD_EVENT_CLOSE)
415     {
416         AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n"));
417 
418         /* This is an unexpected remote disconnect */
419         return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
420     }
421 
422     if (FCB->PollState & AFD_EVENT_ABORT)
423     {
424         AFD_DbgPrint(MIN_TRACE,("Connection aborted\n"));
425 
426         /* This is an abortive socket closure on our side */
427         return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
428     }
429 
430     if (FCB->SendClosed)
431     {
432         AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
433 
434         /* This is a graceful send closure */
435         return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
436     }
437 
438     if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
439         return UnlockAndMaybeComplete
440             ( FCB, STATUS_NO_MEMORY, Irp, 0 );
441 
442     SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
443                                         SendReq->BufferCount,
444                                         NULL, NULL,
445                                         FALSE, FALSE, LockMode );
446 
447     if( !SendReq->BufferArray ) {
448         return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
449                                        Irp, 0 );
450     }
451 
452     AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State));
453 
454     if( FCB->State != SOCKET_STATE_CONNECTED ) {
455         AFD_DbgPrint(MID_TRACE,("Socket not connected\n"));
456         UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
457         return UnlockAndMaybeComplete( FCB, STATUS_INVALID_CONNECTION, Irp, 0 );
458     }
459 
460     AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n",
461                             FCB->Send.BytesUsed));
462 
463     SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
464 
465     AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n",
466                             SpaceAvail));
467 
468     /* Count the total transfer size */
469     SendLength = 0;
470     for (i = 0; i < SendReq->BufferCount; i++)
471     {
472         SendLength += SendReq->BufferArray[i].len;
473     }
474 
475     /* Make sure we've got the space */
476     if (SendLength > SpaceAvail)
477     {
478         /* Blocking sockets have to wait here */
479         if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
480         {
481             FCB->PollState &= ~AFD_EVENT_SEND;
482             return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
483         }
484 
485         /* Check if we can send anything */
486         if (SpaceAvail == 0)
487         {
488             FCB->PollState &= ~AFD_EVENT_SEND;
489 
490             /* Non-overlapped sockets will fail if we can send nothing */
491             if (!(SendReq->AfdFlags & AFD_OVERLAPPED))
492             {
493                 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
494                 return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 );
495             }
496             else
497             {
498                 /* Overlapped sockets just pend */
499                 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
500             }
501         }
502     }
503 
504     for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ )
505     {
506         BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail);
507 
508         AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n",
509                                 i,
510                                 SendReq->BufferArray[i].buf,
511                                 BytesCopied,
512                                 FCB->Send.Window + FCB->Send.BytesUsed));
513 
514         RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed,
515                       SendReq->BufferArray[i].buf,
516                       BytesCopied);
517 
518         TotalBytesCopied += BytesCopied;
519         SpaceAvail -= BytesCopied;
520         FCB->Send.BytesUsed += BytesCopied;
521     }
522 
523     Irp->IoStatus.Information = TotalBytesCopied;
524 
525     if( TotalBytesCopied == 0 ) {
526         AFD_DbgPrint(MID_TRACE,("Empty send\n"));
527         UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
528         return UnlockAndMaybeComplete
529         ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied );
530     }
531 
532     if (SpaceAvail)
533     {
534         FCB->PollState |= AFD_EVENT_SEND;
535         FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
536         PollReeval( FCB->DeviceExt, FCB->FileObject );
537     }
538     else
539     {
540         FCB->PollState &= ~AFD_EVENT_SEND;
541     }
542 
543     /* We use the IRP tail for some temporary storage here */
544     Irp->Tail.Overlay.DriverContext[3] = (PVOID)Irp->IoStatus.Information;
545 
546     Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
547     if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest)
548     {
549         TdiSend(&FCB->SendIrp.InFlightRequest,
550                 FCB->Connection.Object,
551                 0,
552                 FCB->Send.Window,
553                 FCB->Send.BytesUsed,
554                 SendComplete,
555                 FCB);
556     }
557 
558     SocketStateUnlock(FCB);
559 
560     return STATUS_PENDING;
561 }
562 
563 NTSTATUS NTAPI
AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp)564 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
565                          PIO_STACK_LOCATION IrpSp) {
566     NTSTATUS Status = STATUS_SUCCESS;
567     PTDI_CONNECTION_INFORMATION TargetAddress;
568     PFILE_OBJECT FileObject = IrpSp->FileObject;
569     PAFD_FCB FCB = FileObject->FsContext;
570     PAFD_SEND_INFO_UDP SendReq;
571     KPROCESSOR_MODE LockMode;
572 
573     UNREFERENCED_PARAMETER(DeviceObject);
574 
575     AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
576 
577     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
578 
579     FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
580 
581     /* Check that the socket is bound */
582     if( FCB->State != SOCKET_STATE_BOUND &&
583         FCB->State != SOCKET_STATE_CREATED)
584     {
585         AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
586         return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
587     }
588 
589     if (FCB->SendClosed)
590     {
591         AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
592         return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
593     }
594 
595     if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
596         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
597 
598     if (FCB->State == SOCKET_STATE_CREATED)
599     {
600         if (FCB->LocalAddress)
601         {
602             ExFreePoolWithTag(FCB->LocalAddress, TAG_AFD_TRANSPORT_ADDRESS);
603         }
604 
605         FCB->LocalAddress =
606         TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
607                                       Address[0].AddressType );
608 
609         if( FCB->LocalAddress ) {
610             Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD );
611 
612             if( NT_SUCCESS(Status) )
613                 FCB->State = SOCKET_STATE_BOUND;
614             else
615                 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
616         } else
617             return UnlockAndMaybeComplete
618             ( FCB, STATUS_NO_MEMORY, Irp, 0 );
619     }
620 
621     SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
622                                         SendReq->BufferCount,
623                                         NULL, NULL,
624                                         FALSE, FALSE, LockMode );
625 
626     if( !SendReq->BufferArray )
627         return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
628                                        Irp, 0 );
629 
630     AFD_DbgPrint
631         (MID_TRACE,("RemoteAddress #%d Type %u\n",
632                     ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
633                     TAAddressCount,
634                     ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
635                     Address[0].AddressType));
636 
637     Status = TdiBuildConnectionInfo( &TargetAddress,
638                             ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) );
639 
640     /* Check the size of the Address given ... */
641 
642     if( NT_SUCCESS(Status) ) {
643         FCB->PollState &= ~AFD_EVENT_SEND;
644 
645         Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
646         if (Status == STATUS_PENDING)
647         {
648             Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
649                                      FCB->AddressFile.Object,
650                                      SendReq->BufferArray[0].buf,
651                                      SendReq->BufferArray[0].len,
652                                      TargetAddress,
653                                      PacketSocketSendComplete,
654                                      FCB);
655             if (Status != STATUS_PENDING)
656             {
657                 NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry);
658                 Irp->IoStatus.Status = Status;
659                 Irp->IoStatus.Information = 0;
660                 (void)IoSetCancelRoutine(Irp, NULL);
661                 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
662                 UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp));
663                 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
664             }
665         }
666 
667         ExFreePoolWithTag(TargetAddress, TAG_AFD_TDI_CONNECTION_INFORMATION);
668 
669         SocketStateUnlock(FCB);
670 
671         return STATUS_PENDING;
672     }
673     else
674     {
675         UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
676         return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
677     }
678 }
679