[TCPIP, IP]
[reactos.git] / drivers / network / afd / afd / write.c
index ff18894..427dd01 100644 (file)
@@ -35,124 +35,131 @@ static NTSTATUS NTAPI SendComplete
      */
 
     AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
-                           Irp->IoStatus.Status,
-                           Irp->IoStatus.Information));
+                                                       Irp->IoStatus.Status,
+                                                       Irp->IoStatus.Information));
 
-    ASSERT_IRQL(APC_LEVEL);
-
-    if( !SocketAcquireStateLock( FCB ) ) return Status;
+    if( !SocketAcquireStateLock( FCB ) )
+        return STATUS_FILE_CLOSED;
 
     FCB->SendIrp.InFlightRequest = NULL;
     /* Request is not in flight any longer */
 
     if( FCB->State == SOCKET_STATE_CLOSED ) {
+        /* Cleanup our IRP queue because the FCB is being destroyed */
+        while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
+              NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
+              NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+              NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+              SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+              NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
+              NextIrp->IoStatus.Information = 0;
+              UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+              if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+               (void)IoSetCancelRoutine(NextIrp, NULL);
+              IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+        }
        SocketStateUnlock( FCB );
-       DestroySocket( FCB );
-       return STATUS_SUCCESS;
+       return STATUS_FILE_CLOSED;
     }
 
     if( !NT_SUCCESS(Status) ) {
-       /* Complete all following send IRPs with error */
-
-       while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
-           NextIrpEntry =
-               RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
-           NextIrp =
-               CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
-           NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
-           SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+               /* Complete all following send IRPs with error */
 
-           UnlockBuffers( SendReq->BufferArray,
-                          SendReq->BufferCount,
-                          FALSE );
+               while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
+                       NextIrpEntry =
+                               RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
+                       NextIrp =
+                               CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+                       NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+                       SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
 
-           NextIrp->IoStatus.Status = Status;
-           NextIrp->IoStatus.Information = 0;
+                       UnlockBuffers( SendReq->BufferArray,
+                                                  SendReq->BufferCount,
+                                                  FALSE );
 
-           if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+                       NextIrp->IoStatus.Status = Status;
+                       NextIrp->IoStatus.Information = 0;
 
-           IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
-       }
+                       if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+                        (void)IoSetCancelRoutine(NextIrp, NULL);
+                       IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+               }
 
-       SocketStateUnlock( FCB );
+               SocketStateUnlock( FCB );
 
-       return STATUS_SUCCESS;
+               return STATUS_SUCCESS;
     }
 
     RtlMoveMemory( FCB->Send.Window,
-                  FCB->Send.Window + FCB->Send.BytesUsed,
-                  FCB->Send.BytesUsed - Irp->IoStatus.Information );
+                                  FCB->Send.Window + FCB->Send.BytesUsed,
+                                  FCB->Send.BytesUsed - Irp->IoStatus.Information );
     FCB->Send.BytesUsed -= Irp->IoStatus.Information;
 
     if( !FCB->Send.BytesUsed &&
-       !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
-       NextIrpEntry =
-           RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
-       NextIrp =
-           CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
-       NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
-       SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
-       Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
+               !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
+               NextIrpEntry =
+                       RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
+               NextIrp =
+                       CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+               NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+               SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+               Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
 
-       AFD_DbgPrint(MID_TRACE,("SendReq @ %x\n", SendReq));
+               AFD_DbgPrint(MID_TRACE,("SendReq @ %x\n", SendReq));
 
-       SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
+               SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
 
-       for( i = 0; i < SendReq->BufferCount; i++ ) {
-           Map[i].BufferAddress =
-               MmMapLockedPages( Map[i].Mdl, KernelMode );
+               for( i = 0; i < SendReq->BufferCount; i++ ) {
+                       Map[i].BufferAddress =
+                               MmMapLockedPages( Map[i].Mdl, KernelMode );
 
-           CopySize = MIN( SpaceAvail,
-                           SendReq->BufferArray[i].len );
+                       CopySize = MIN( SpaceAvail,
+                                                       SendReq->BufferArray[i].len );
 
-           RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
-                          Map[i].BufferAddress,
-                          CopySize );
+                       RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
+                                                  Map[i].BufferAddress,
+                                                  CopySize );
 
-           MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
+                       MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
 
-           FCB->Send.BytesUsed += CopySize;
-           TotalBytesCopied += CopySize;
-           SpaceAvail -= CopySize;
-       }
+                       FCB->Send.BytesUsed += CopySize;
+                       TotalBytesCopied += CopySize;
+                       SpaceAvail -= CopySize;
+               }
     }
 
     /* Some data is still waiting */
     if( FCB->Send.BytesUsed ) {
-       FCB->PollState &= ~AFD_EVENT_SEND;
-
-       SocketCalloutEnter( FCB );
-
-       Status = TdiSend( &FCB->SendIrp.InFlightRequest,
-                         FCB->Connection.Object,
-                         0,
-                         FCB->Send.Window,
-                         FCB->Send.BytesUsed,
-                         &FCB->SendIrp.Iosb,
-                         SendComplete,
-                         FCB );
-
-       SocketCalloutLeave( FCB );
+               FCB->PollState &= ~AFD_EVENT_SEND;
+
+               Status = TdiSend( &FCB->SendIrp.InFlightRequest,
+                                                 FCB->Connection.Object,
+                                                 0,
+                                                 FCB->Send.Window,
+                                                 FCB->Send.BytesUsed,
+                                                 &FCB->SendIrp.Iosb,
+                                                 SendComplete,
+                                                 FCB );
     } else {
-       FCB->PollState |= AFD_EVENT_SEND;
-       PollReeval( FCB->DeviceExt, FCB->FileObject );
+               FCB->PollState |= AFD_EVENT_SEND;
     }
 
+    PollReeval( FCB->DeviceExt, FCB->FileObject );
+
     if( TotalBytesCopied > 0 ) {
-       UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
+               UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
 
-       if( Status == STATUS_PENDING )
-           Status = STATUS_SUCCESS;
+               if( Status == STATUS_PENDING )
+                       Status = STATUS_SUCCESS;
 
-       AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
+               AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
 
-       return UnlockAndMaybeComplete( FCB, Status, NextIrp, TotalBytesCopied,
-                                      NULL );
+               return UnlockAndMaybeComplete( FCB, Status, NextIrp, TotalBytesCopied );
     } else if( NextIrp ) {
-       AFD_DbgPrint(MID_TRACE,("Could not do any more with Irp %x\n",
-                               NextIrp));
-       InsertHeadList( &FCB->PendingIrpList[FUNCTION_SEND],
-                       &NextIrp->Tail.Overlay.ListEntry );
+               AFD_DbgPrint(MID_TRACE,("Could not do any more with Irp %x\n",
+                                                               NextIrp));
+               InsertHeadList( &FCB->PendingIrpList[FUNCTION_SEND],
+                                               &NextIrp->Tail.Overlay.ListEntry );
     }
 
     SocketStateUnlock( FCB );
@@ -165,24 +172,35 @@ static NTSTATUS NTAPI PacketSocketSendComplete
   PIRP Irp,
   PVOID Context ) {
     PAFD_FCB FCB = (PAFD_FCB)Context;
+    PLIST_ENTRY NextIrpEntry;
+    PIRP NextIrp;
 
     AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
-                           Irp->IoStatus.Status,
-                           Irp->IoStatus.Information));
+                                                       Irp->IoStatus.Status,
+                                                       Irp->IoStatus.Information));
 
-    /* It's ok if the FCB already died */
-    if( !SocketAcquireStateLock( FCB ) ) return STATUS_SUCCESS;
-
-    FCB->PollState |= AFD_EVENT_SEND;
-    PollReeval( FCB->DeviceExt, FCB->FileObject );
+    if( !SocketAcquireStateLock( FCB ) )
+        return STATUS_FILE_CLOSED;
 
     FCB->SendIrp.InFlightRequest = NULL;
     /* Request is not in flight any longer */
 
+    FCB->PollState |= AFD_EVENT_SEND;
+    PollReeval( FCB->DeviceExt, FCB->FileObject );
+
     if( FCB->State == SOCKET_STATE_CLOSED ) {
+        /* Cleanup our IRP queue because the FCB is being destroyed */
+        while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
+              NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
+              NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+              NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
+              NextIrp->IoStatus.Information = 0;
+              if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+               (void)IoSetCancelRoutine(NextIrp, NULL);
+              IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+        }
        SocketStateUnlock( FCB );
-       DestroySocket( FCB );
-       return STATUS_SUCCESS;
+       return STATUS_FILE_CLOSED;
     }
 
     SocketStateUnlock( FCB );
@@ -190,22 +208,21 @@ static NTSTATUS NTAPI PacketSocketSendComplete
     return STATUS_SUCCESS;
 }
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
-                           PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
+                                                       PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
     NTSTATUS Status = STATUS_SUCCESS;
     PFILE_OBJECT FileObject = IrpSp->FileObject;
     PAFD_FCB FCB = FileObject->FsContext;
     PAFD_SEND_INFO SendReq;
+       ULONG Information;
     UINT TotalBytesCopied = 0, i, CopySize = 0,
-       SpaceAvail = 0, TotalBytesEncountered = 0;
+               SpaceAvail = 0, TotalBytesEncountered = 0;
 
     AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
 
     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
 
-    FCB->EventsFired &= ~AFD_EVENT_SEND;
-
     if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
     {
         PAFD_SEND_INFO_UDP SendReq;
@@ -213,12 +230,11 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
         /* Check that the socket is bound */
         if( FCB->State != SOCKET_STATE_BOUND )
-            return UnlockAndMaybeComplete( FCB, STATUS_UNSUCCESSFUL, Irp,
-                                           0, NULL );
+            return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp,
+                                           0 );
 
         if( !(SendReq = LockRequest( Irp, IrpSp )) )
-            return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0,
-                                           NULL );
+            return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 );
 
         /* Must lock buffers before handing off user data */
         SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
@@ -226,16 +242,14 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                             NULL, NULL,
                                             FALSE, FALSE );
 
-       if( !SendReq->BufferArray ) {
-           return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
-                                           Irp, 0, NULL );
-       }
+               if( !SendReq->BufferArray ) {
+                       return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
+                                           Irp, 0 );
+               }
 
         TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
 
-       if( TargetAddress ) {
-            SocketCalloutEnter( FCB );
-
+               if( TargetAddress ) {
             Status = TdiSendDatagram
                 ( &FCB->SendIrp.InFlightRequest,
                   FCB->AddressFile.Object,
@@ -246,189 +260,192 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                   PacketSocketSendComplete,
                   FCB );
 
-           SocketCalloutLeave( FCB );
-
-           ExFreePool( TargetAddress );
-       } else Status = STATUS_NO_MEMORY;
+                       ExFreePool( TargetAddress );
+               } else Status = STATUS_NO_MEMORY;
 
         if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
 
         AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
 
-        return UnlockAndMaybeComplete( FCB, Status, Irp,
-                                       SendReq->BufferArray[0].len,
-                                       NULL );
+               /* Even if we were pended, we're done with the user buffer at this
+                * point. */
+               Information = SendReq->BufferArray[0].len;
+               UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+        return UnlockAndMaybeComplete( FCB, Status, Irp, Information );
     }
 
     if( !(SendReq = LockRequest( Irp, IrpSp )) )
-       return UnlockAndMaybeComplete
-           ( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied, NULL );
+               return UnlockAndMaybeComplete
+                       ( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied );
+
+    SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
+                                                                               SendReq->BufferCount,
+                                                                               NULL, NULL,
+                                                                               FALSE, FALSE );
+
+    if( !SendReq->BufferArray ) {
+        return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
+                                       Irp, 0 );
+    }
 
     AFD_DbgPrint(MID_TRACE,("Socket state %d\n", FCB->State));
 
     if( FCB->State != SOCKET_STATE_CONNECTED ) {
-       if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
-           AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
-           return UnlockAndMaybeComplete
-               ( FCB, STATUS_CANT_WAIT, Irp, 0, NULL );
-       } else {
-           AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
-           return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
-       }
+               if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
+                       AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
+                       UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
+                       return UnlockAndMaybeComplete
+                               ( FCB, STATUS_CANT_WAIT, Irp, 0 );
+               } else {
+                       AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
+                       return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
+               }
     }
 
-    AFD_DbgPrint(MID_TRACE,("We already have %d bytes waiting.\n",
-                           FCB->Send.BytesUsed));
-
     AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n",
-                           FCB->Send.BytesUsed));
+                                                       FCB->Send.BytesUsed));
 
     if( !FCB->Send.BytesUsed ) {
-       SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
-
-       AFD_DbgPrint(MID_TRACE,("We can accept %d bytes\n",
-                               SpaceAvail));
-
-        SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
-                                           SendReq->BufferCount,
-                                           NULL, NULL,
-                                           FALSE, FALSE );
-
-        if( !SendReq->BufferArray ) {
-            return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
-                                           Irp, 0, NULL );
-        }
+               SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
 
-       for( i = 0; FCB->Send.BytesUsed < FCB->Send.Size &&
-                i < SendReq->BufferCount; i++ ) {
-           CopySize = MIN( SpaceAvail,
-                           SendReq->BufferArray[i].len );
+               AFD_DbgPrint(MID_TRACE,("We can accept %d bytes\n",
+                                                               SpaceAvail));
 
-           TotalBytesEncountered += SendReq->BufferArray[i].len;
+               for( i = 0; FCB->Send.BytesUsed < FCB->Send.Size &&
+                                i < SendReq->BufferCount; i++ ) {
+                       CopySize = MIN( SpaceAvail,
+                                                       SendReq->BufferArray[i].len );
 
-           AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n",
-                                   i,
-                                   SendReq->BufferArray[i].buf,
-                                   CopySize,
-                                   FCB->Send.Window + FCB->Send.BytesUsed));
+                       TotalBytesEncountered += SendReq->BufferArray[i].len;
 
-           RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
-                          SendReq->BufferArray[i].buf,
-                          CopySize );
+                       AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n",
+                                                                       i,
+                                                                       SendReq->BufferArray[i].buf,
+                                                                       CopySize,
+                                                                       FCB->Send.Window + FCB->Send.BytesUsed));
 
-           FCB->Send.BytesUsed += CopySize;
-           TotalBytesCopied += CopySize;
-           SpaceAvail -= CopySize;
-       }
+                       RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
+                                                  SendReq->BufferArray[i].buf,
+                                                  CopySize );
 
-       if( TotalBytesEncountered == 0 ) {
-           UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
+                       FCB->Send.BytesUsed += CopySize;
+                       TotalBytesCopied += CopySize;
+                       SpaceAvail -= CopySize;
+               }
 
-           AFD_DbgPrint(MID_TRACE,("Empty send\n"));
-           return UnlockAndMaybeComplete
-               ( FCB, Status, Irp, TotalBytesCopied, NULL );
-       }
+               if( TotalBytesEncountered == 0 ) {
+                       UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
 
-       AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
+                       AFD_DbgPrint(MID_TRACE,("Empty send\n"));
+                       return UnlockAndMaybeComplete
+                               ( FCB, Status, Irp, TotalBytesCopied );
+               }
 
-       if( TotalBytesCopied > 0 ) {
-           UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
+               AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
 
-           FCB->SendIrp.InFlightRequest = (PVOID)1; /* Placeholder */
+               if( TotalBytesCopied > 0 ) {
+                       UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
 
-           SocketCalloutEnter( FCB );
+                       Status = TdiSend( &FCB->SendIrp.InFlightRequest,
+                                                         FCB->Connection.Object,
+                                                         0,
+                                                         FCB->Send.Window,
+                                                         FCB->Send.BytesUsed,
+                                                         &FCB->SendIrp.Iosb,
+                                                         SendComplete,
+                                                         FCB );
 
-           Status = TdiSend( &FCB->SendIrp.InFlightRequest,
-                             FCB->Connection.Object,
-                             0,
-                             FCB->Send.Window,
-                             FCB->Send.BytesUsed,
-                             &FCB->SendIrp.Iosb,
-                             SendComplete,
-                             FCB );
+                       if( Status == STATUS_PENDING )
+                               Status = STATUS_SUCCESS;
 
-           SocketCalloutLeave( FCB );
+                       AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n",
+                                                                       Status, TotalBytesCopied));
 
-           if( Status == STATUS_PENDING )
-               Status = STATUS_SUCCESS;
-
-           AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n",
-                                   Status, TotalBytesCopied));
-
-           return UnlockAndMaybeComplete
-               ( FCB, Status, Irp, TotalBytesCopied, NULL );
-       }
+                       return UnlockAndMaybeComplete
+                               ( FCB, Status, Irp, TotalBytesCopied );
+               }
     }
 
     if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
-       AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
-       return UnlockAndMaybeComplete
-           ( FCB, STATUS_CANT_WAIT, Irp, 0, NULL );
+               AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
+               UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
+               return UnlockAndMaybeComplete
+                       ( FCB, STATUS_CANT_WAIT, Irp, 0 );
     } else {
-       AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
-       return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
+               AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
+               return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
     }
 }
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
-                        PIO_STACK_LOCATION IrpSp) {
+                                                PIO_STACK_LOCATION IrpSp) {
     NTSTATUS Status = STATUS_SUCCESS;
     PTDI_CONNECTION_INFORMATION TargetAddress;
     PFILE_OBJECT FileObject = IrpSp->FileObject;
     PAFD_FCB FCB = FileObject->FsContext;
     PAFD_SEND_INFO_UDP SendReq;
+       ULONG Information;
 
     AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
 
     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
 
-    FCB->EventsFired &= ~AFD_EVENT_SEND;
     FCB->PollState &= ~AFD_EVENT_SEND;
 
+    PollReeval( FCB->DeviceExt, FCB->FileObject );
+
     /* Check that the socket is bound */
     if( FCB->State != SOCKET_STATE_BOUND )
-       return UnlockAndMaybeComplete
-           ( FCB, STATUS_UNSUCCESSFUL, Irp, 0, NULL );
+               return UnlockAndMaybeComplete
+                       ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
     if( !(SendReq = LockRequest( Irp, IrpSp )) )
-       return UnlockAndMaybeComplete
-           ( FCB, STATUS_NO_MEMORY, Irp, 0, NULL );
+               return UnlockAndMaybeComplete
+                       ( FCB, STATUS_NO_MEMORY, Irp, 0 );
+
+    SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
+                                        SendReq->BufferCount,
+                                        NULL, NULL,
+                                        FALSE, FALSE );
+
+    if( !SendReq->BufferArray )
+               return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
+                                       Irp, 0 );
 
     AFD_DbgPrint
-       (MID_TRACE,("RemoteAddress #%d Type %d\n",
-                   ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
-                   TAAddressCount,
-                   ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
-                   Address[0].AddressType));
+               (MID_TRACE,("RemoteAddress #%d Type %d\n",
+                                       ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
+                                       TAAddressCount,
+                                       ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
+                                       Address[0].AddressType));
 
     TdiBuildConnectionInfo( &TargetAddress,
-                           ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress) );
+                                                       ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) );
 
     /* Check the size of the Address given ... */
 
     if( TargetAddress ) {
-       SocketCalloutEnter( FCB );
-
-       Status = TdiSendDatagram
-           ( &FCB->SendIrp.InFlightRequest,
-             FCB->AddressFile.Object,
-             SendReq->BufferArray[0].buf,
-             SendReq->BufferArray[0].len,
-             TargetAddress,
-             &FCB->SendIrp.Iosb,
-             PacketSocketSendComplete,
-             FCB );
-
-       SocketCalloutLeave( FCB );
+               Status = TdiSendDatagram
+                       ( &FCB->SendIrp.InFlightRequest,
+                         FCB->AddressFile.Object,
+                         SendReq->BufferArray[0].buf,
+                         SendReq->BufferArray[0].len,
+                         TargetAddress,
+                         &FCB->SendIrp.Iosb,
+                         PacketSocketSendComplete,
+                         FCB );
 
-       ExFreePool( TargetAddress );
+               ExFreePool( TargetAddress );
     } else Status = STATUS_NO_MEMORY;
 
     if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
 
     AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
 
-    return UnlockAndMaybeComplete
-       ( FCB, Status, Irp, SendReq->BufferArray[0].len, NULL );
+       /* Even if we were pended, we're done with the user buffer at this
+        * point. */
+       Information = SendReq->BufferArray[0].len;
+       UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+    return UnlockAndMaybeComplete( FCB, Status, Irp, Information );
 }