- Fix a race condition that occurs when an IRP gets cancelled after it is inserted...
[reactos.git] / reactos / drivers / network / tcpip / tcpip / dispatch.c
index a5f4a15..c6f2d2a 100644 (file)
  */
 
 #include "precomp.h"
-#include <pseh/pseh.h>
+#include <pseh/pseh2.h>
+
+
+NTSTATUS IRPFinish( PIRP Irp, NTSTATUS Status ) {
+    KIRQL OldIrql;
+
+    Irp->IoStatus.Status = Status;
+
+    if( Status == STATUS_PENDING )
+       IoMarkIrpPending( Irp );
+    else {
+        IoAcquireCancelSpinLock(&OldIrql);
+       (void)IoSetCancelRoutine( Irp, NULL );
+        IoReleaseCancelSpinLock(OldIrql);
+
+       IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
+    }
+
+    return Status;
+}
 
 NTSTATUS DispPrepareIrpForCancel(
     PTRANSPORT_CONTEXT Context,
@@ -27,13 +46,17 @@ NTSTATUS DispPrepareIrpForCancel(
  */
 {
     KIRQL OldIrql;
+    PIO_STACK_LOCATION IrpSp;
+    PTRANSPORT_CONTEXT TransContext;
 
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
+    IrpSp       = IoGetCurrentIrpStackLocation(Irp);
+    TransContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
+
     IoAcquireCancelSpinLock(&OldIrql);
 
-    if (!Irp->Cancel) {
-        IoMarkIrpPending(Irp);
+    if (!Irp->Cancel && !TransContext->CancelIrps) {
         (void)IoSetCancelRoutine(Irp, CancelRoutine);
         IoReleaseCancelSpinLock(OldIrql);
 
@@ -51,37 +74,9 @@ NTSTATUS DispPrepareIrpForCancel(
 
     TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n"));
 
-    return IRPFinish(Irp, STATUS_CANCELLED);
+    return Irp->IoStatus.Status;
 }
 
-
-VOID DispCancelComplete(
-    PVOID Context)
-/*
- * FUNCTION: Completes a cancel request
- * ARGUMENTS:
- *     Context = Pointer to context information (FILE_OBJECT)
- */
-{
-    /*KIRQL OldIrql;*/
-    PFILE_OBJECT FileObject;
-    PTRANSPORT_CONTEXT TranContext;
-
-    TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
-
-    FileObject  = (PFILE_OBJECT)Context;
-    TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
-
-    /* Set the cleanup event */
-    KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
-
-    /* We are expected to release the cancel spin lock */
-    /*IoReleaseCancelSpinLock(OldIrql);*/
-
-    TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
-}
-
-
 VOID DispDataRequestComplete(
     PVOID Context,
     NTSTATUS Status,
@@ -96,7 +91,6 @@ VOID DispDataRequestComplete(
 {
     PIRP Irp;
     PIO_STACK_LOCATION IrpSp;
-    PTRANSPORT_CONTEXT TranContext;
     KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
@@ -104,21 +98,11 @@ VOID DispDataRequestComplete(
 
     Irp         = Context;
     IrpSp       = IoGetCurrentIrpStackLocation(Irp);
-    TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
 
     IoAcquireCancelSpinLock(&OldIrql);
 
     (void)IoSetCancelRoutine(Irp, NULL);
 
-    if (Irp->Cancel || TranContext->CancelIrps) {
-        /* The IRP has been cancelled */
-
-        TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n"));
-
-        Status = STATUS_CANCELLED;
-        Count  = 0;
-    }
-
     IoReleaseCancelSpinLock(OldIrql);
 
     Irp->IoStatus.Status      = Status;
@@ -130,36 +114,11 @@ VOID DispDataRequestComplete(
                            Irp->IoStatus.Information));
     TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
 
-    IRPFinish(Irp, Irp->IoStatus.Status);
+    IRPFinish(Irp, Status);
 
     TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
 }
 
-typedef struct _DISCONNECT_TYPE {
-    UINT Type;
-    PVOID Context;
-    PIRP Irp;
-    PFILE_OBJECT FileObject;
-} DISCONNECT_TYPE, *PDISCONNECT_TYPE;
-
-VOID DispDoDisconnect( PVOID Data ) {
-    PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data;
-
-    TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n"));
-    TCPDisconnect
-       ( DisType->Context,
-         DisType->Type,
-         NULL,
-         NULL,
-         DispDataRequestComplete,
-         DisType->Irp );
-    TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n"));
-
-    DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0);
-
-    DispCancelComplete(DisType->FileObject);
-}
-
 VOID NTAPI DispCancelRequest(
     PDEVICE_OBJECT Device,
     PIRP Irp)
@@ -174,9 +133,9 @@ VOID NTAPI DispCancelRequest(
     PTRANSPORT_CONTEXT TranContext;
     PFILE_OBJECT FileObject;
     UCHAR MinorFunction;
-    DISCONNECT_TYPE DisType;
-    PVOID WorkItem;
-    /*NTSTATUS Status = STATUS_SUCCESS;*/
+    BOOLEAN DequeuedIrp = TRUE;
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
 
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -187,9 +146,10 @@ VOID NTAPI DispCancelRequest(
 
     TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X)  MinorFunction (0x%X)  IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
 
-    Irp->IoStatus.Status = STATUS_PENDING;
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    Irp->IoStatus.Information = 0;
 
-#ifdef DBG
+#if DBG
     if (!Irp->Cancel)
         TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
 #endif
@@ -198,48 +158,39 @@ VOID NTAPI DispCancelRequest(
     switch(MinorFunction) {
     case TDI_SEND:
     case TDI_RECEIVE:
-       DisType.Type = TDI_DISCONNECT_RELEASE | 
-           ((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0);
-       DisType.Context = TranContext->Handle.ConnectionContext;
-       DisType.Irp = Irp;
-       DisType.FileObject = FileObject;
-       
-       TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
-
-       if( !ChewCreate( &WorkItem, sizeof(DISCONNECT_TYPE), 
-                        DispDoDisconnect, &DisType ) )
-           ASSERT(0);
+       DequeuedIrp = TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
         break;
 
     case TDI_SEND_DATAGRAM:
-       Irp->IoStatus.Status = STATUS_CANCELLED;
         if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
             TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n"));
             break;
         }
 
-        /*DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp);*/
+        DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
         break;
 
     case TDI_RECEIVE_DATAGRAM:
-       Irp->IoStatus.Status = STATUS_CANCELLED;
         if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
             TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
             break;
         }
 
-        /*DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp);*/
+        DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
+        break;
+
+    case TDI_CONNECT:
+        DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
         break;
 
     default:
         TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
+        ASSERT(FALSE);
         break;
     }
 
-    if( Irp->IoStatus.Status == STATUS_PENDING )
-       IoMarkIrpPending(Irp);
-
-    IoReleaseCancelSpinLock(Irp->CancelIrql);
+    if (DequeuedIrp)
+       IRPFinish(Irp, STATUS_CANCELLED);
 
     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
@@ -259,7 +210,8 @@ VOID NTAPI DispCancelListenRequest(
     PTRANSPORT_CONTEXT TranContext;
     PFILE_OBJECT FileObject;
     PCONNECTION_ENDPOINT Connection;
-    /*NTSTATUS Status = STATUS_SUCCESS;*/
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
 
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -270,22 +222,20 @@ VOID NTAPI DispCancelListenRequest(
 
     TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X).\n", Irp));
 
-#ifdef DBG
+#if DBG
     if (!Irp->Cancel)
         TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
 #endif
 
     /* Try canceling the request */
     Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
-    TCPAbortListenForSocket(
-           Connection->AddressFile->Listener,
-           Connection );
-
-    IoReleaseCancelSpinLock(Irp->CancelIrql);
 
-    DispDataRequestComplete(Irp, STATUS_CANCELLED, 0);
-
-    DispCancelComplete(FileObject);
+    if (TCPAbortListenForSocket(Connection->AddressFile->Listener,
+                                Connection))
+    {
+        Irp->IoStatus.Information = 0;
+        IRPFinish(Irp, STATUS_CANCELLED);
+    }
 
     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
@@ -324,6 +274,7 @@ NTSTATUS DispTdiAssociateAddress(
   PFILE_OBJECT FileObject;
   PADDRESS_FILE AddrFile = NULL;
   NTSTATUS Status;
+  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -343,11 +294,6 @@ NTSTATUS DispTdiAssociateAddress(
     return STATUS_INVALID_PARAMETER;
   }
 
-  if (Connection->AddressFile) {
-    TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
-    return STATUS_INVALID_PARAMETER;
-  }
-
   Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
 
   Status = ObReferenceObjectByHandle(
@@ -363,8 +309,18 @@ NTSTATUS DispTdiAssociateAddress(
     return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
+  if (Connection->AddressFile) {
+    ObDereferenceObject(FileObject);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
+    TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
+    return STATUS_INVALID_PARAMETER;
+  }
+
   if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
     ObDereferenceObject(FileObject);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
     TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
       FileObject->FsContext2));
     return STATUS_INVALID_PARAMETER;
@@ -375,17 +331,21 @@ NTSTATUS DispTdiAssociateAddress(
   TranContext = FileObject->FsContext;
   if (!TranContext) {
     ObDereferenceObject(FileObject);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
     return STATUS_INVALID_PARAMETER;
   }
 
   AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
   if (!AddrFile) {
+      KeReleaseSpinLock(&Connection->Lock, OldIrql);
       ObDereferenceObject(FileObject);
       TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
       return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLockAtDpcLevel(&AddrFile->Lock);
+
   Connection->AddressFile = AddrFile;
 
   /* Add connection endpoint to the address file */
@@ -394,6 +354,9 @@ NTSTATUS DispTdiAssociateAddress(
   /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
   ObDereferenceObject(FileObject);
 
+  KeReleaseSpinLockFromDpcLevel(&AddrFile->Lock);
+  KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
   return Status;
 }
 
@@ -423,23 +386,37 @@ NTSTATUS DispTdiConnect(
   TranContext = IrpSp->FileObject->FsContext;
   if (!TranContext) {
     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-    return STATUS_INVALID_CONNECTION;
+    Status = STATUS_INVALID_PARAMETER;
+    goto done;
   }
 
   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
   if (!Connection) {
     TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
-    return STATUS_INVALID_CONNECTION;
+    Status = STATUS_INVALID_PARAMETER;
+    goto done;
   }
 
   Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
 
-  Status = TCPConnect(
-      TranContext->Handle.ConnectionContext,
-      Parameters->RequestConnectionInformation,
-      Parameters->ReturnConnectionInformation,
-      DispDataRequestComplete,
-      Irp );
+  Status = DispPrepareIrpForCancel(TranContext->Handle.ConnectionContext,
+                                   Irp,
+                                   DispCancelRequest);
+
+  if (NT_SUCCESS(Status)) {
+      Status = TCPConnect(
+          TranContext->Handle.ConnectionContext,
+          Parameters->RequestConnectionInformation,
+          Parameters->ReturnConnectionInformation,
+          DispDataRequestComplete,
+          Irp );
+  }
+
+done:
+  if (Status != STATUS_PENDING) {
+      DispDataRequestComplete(Irp, Status, 0);
+  } else
+      IoMarkIrpPending(Irp);
 
   TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
 
@@ -460,6 +437,7 @@ NTSTATUS DispTdiDisassociateAddress(
   PCONNECTION_ENDPOINT Connection;
   PTRANSPORT_CONTEXT TranContext;
   PIO_STACK_LOCATION IrpSp;
+  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -479,11 +457,26 @@ NTSTATUS DispTdiDisassociateAddress(
     return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
   if (!Connection->AddressFile) {
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
     TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n"));
     return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLockAtDpcLevel(&Connection->AddressFile->Lock);
+
+  /* Remove this connection from the address file */
+  Connection->AddressFile->Connection = NULL;
+
+  KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock);
+
+  /* Remove the address file from this connection */
+  Connection->AddressFile = NULL;
+
+  KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
   return STATUS_SUCCESS;
 }
 
@@ -514,13 +507,15 @@ NTSTATUS DispTdiDisconnect(
   TranContext = IrpSp->FileObject->FsContext;
   if (!TranContext) {
     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-    return STATUS_INVALID_CONNECTION;
+    Status = STATUS_INVALID_PARAMETER;
+    goto done;
   }
 
   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
   if (!Connection) {
     TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
-    return STATUS_INVALID_CONNECTION;
+    Status = STATUS_INVALID_PARAMETER;
+    goto done;
   }
 
   Status = TCPDisconnect(
@@ -531,7 +526,13 @@ NTSTATUS DispTdiDisconnect(
       DispDataRequestComplete,
       Irp );
 
-  TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
+done:
+   if (Status != STATUS_PENDING) {
+       DispDataRequestComplete(Irp, Status, 0);
+   } else
+       IoMarkIrpPending(Irp);
+
+  TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status));
 
   return Status;
 }
@@ -552,6 +553,7 @@ NTSTATUS DispTdiListen(
   PTRANSPORT_CONTEXT TranContext;
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status = STATUS_SUCCESS;
+  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -563,31 +565,43 @@ NTSTATUS DispTdiListen(
   if (TranContext == NULL)
     {
       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-      return STATUS_INVALID_CONNECTION;
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
     }
 
   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
   if (Connection == NULL)
     {
       TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
-      return STATUS_INVALID_CONNECTION;
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
     }
 
   Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
 
-  TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile: %x\n",
-                         Connection->AddressFile ));
-  if( Connection->AddressFile ) {
-      TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile->Listener: %x\n",
-                             Connection->AddressFile->Listener));
+  Status = DispPrepareIrpForCancel
+      (TranContext->Handle.ConnectionContext,
+       Irp,
+       (PDRIVER_CANCEL)DispCancelListenRequest);
+
+  KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
+  if (Connection->AddressFile == NULL)
+  {
+     TI_DbgPrint(MID_TRACE, ("No associated address file\n"));
+     KeReleaseSpinLock(&Connection->Lock, OldIrql);
+     Status = STATUS_INVALID_PARAMETER;
+     goto done;
   }
 
+  KeAcquireSpinLockAtDpcLevel(&Connection->AddressFile->Lock);
+
   /* Listening will require us to create a listening socket and store it in
    * the address file.  It will be signalled, and attempt to complete an irp
    * when a new connection arrives. */
   /* The important thing to note here is that the irp we'll complete belongs
    * to the socket to be accepted onto, not the listener */
-  if( !Connection->AddressFile->Listener ) {
+  if( NT_SUCCESS(Status) && !Connection->AddressFile->Listener ) {
       Connection->AddressFile->Listener =
          TCPAllocateConnectionEndpoint( NULL );
 
@@ -608,12 +622,6 @@ NTSTATUS DispTdiListen(
          Status = TCPListen( Connection->AddressFile->Listener, 1024 );
          /* BACKLOG */
   }
-  if( NT_SUCCESS(Status) ) {
-      Status = DispPrepareIrpForCancel
-          (TranContext->Handle.ConnectionContext,
-           Irp,
-           (PDRIVER_CANCEL)DispCancelListenRequest);
-  }
 
   if( NT_SUCCESS(Status) ) {
       Status = TCPAccept
@@ -624,6 +632,15 @@ NTSTATUS DispTdiListen(
            Irp );
   }
 
+  KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock);
+  KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
+done:
+  if (Status != STATUS_PENDING) {
+      DispDataRequestComplete(Irp, Status, 0);
+  } else
+      IoMarkIrpPending(Irp);
+
   TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status));
 
   return Status;
@@ -654,7 +671,7 @@ NTSTATUS DispTdiQueryInformation(
   TranContext = IrpSp->FileObject->FsContext;
   if (!TranContext) {
     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-    return STATUS_INVALID_CONNECTION;
+    return STATUS_INVALID_PARAMETER;
   }
 
   switch (Parameters->QueryType)
@@ -664,49 +681,45 @@ NTSTATUS DispTdiQueryInformation(
         PTDI_ADDRESS_INFO AddressInfo;
         PADDRESS_FILE AddrFile;
         PTA_IP_ADDRESS Address;
+        PCONNECTION_ENDPOINT Endpoint = NULL;
+
+
+        if (MmGetMdlByteCount(Irp->MdlAddress) <
+            (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
+             sizeof(TDI_ADDRESS_IP))) {
+          TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
+          return STATUS_BUFFER_TOO_SMALL;
+        }
 
         AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
+               Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
 
         switch ((ULONG)IrpSp->FileObject->FsContext2) {
           case TDI_TRANSPORT_ADDRESS_FILE:
             AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
-            break;
+
+                       Address->TAAddressCount = 1;
+                       Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
+                       Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
+                       Address->Address[0].Address[0].sin_port = AddrFile->Port;
+                       Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address;
+                       RtlZeroMemory(
+                               &Address->Address[0].Address[0].sin_zero,
+                               sizeof(Address->Address[0].Address[0].sin_zero));
+                       return STATUS_SUCCESS;
 
           case TDI_CONNECTION_FILE:
-            AddrFile =
-              ((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)->
-              AddressFile;
-            break;
+            Endpoint =
+                               (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
+                       RtlZeroMemory(
+                               &Address->Address[0].Address[0].sin_zero,
+                               sizeof(Address->Address[0].Address[0].sin_zero));
+                       return TCPGetSockAddress( Endpoint, (PTRANSPORT_ADDRESS)Address, FALSE );
 
           default:
             TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
             return STATUS_INVALID_PARAMETER;
         }
-
-        if (!AddrFile) {
-          TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
-          return STATUS_INVALID_PARAMETER;
-        }
-
-        if (MmGetMdlByteCount(Irp->MdlAddress) <
-            (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
-             sizeof(TDI_ADDRESS_IP))) {
-          TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
-          return STATUS_BUFFER_OVERFLOW;
-        }
-
-        Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
-        Address->TAAddressCount = 1;
-        Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
-        Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
-        Address->Address[0].Address[0].sin_port = AddrFile->Port;
-        Address->Address[0].Address[0].in_addr =
-          AddrFile->Address.Address.IPv4Address;
-        RtlZeroMemory(
-          &Address->Address[0].Address[0].sin_zero,
-          sizeof(Address->Address[0].Address[0].sin_zero));
-
-        return STATUS_SUCCESS;
       }
 
     case TDI_QUERY_CONNECTION_INFO:
@@ -715,12 +728,20 @@ NTSTATUS DispTdiQueryInformation(
         PADDRESS_FILE AddrFile;
         PCONNECTION_ENDPOINT Endpoint = NULL;
 
+        if (MmGetMdlByteCount(Irp->MdlAddress) <
+            (FIELD_OFFSET(TDI_CONNECTION_INFORMATION, RemoteAddress) +
+             sizeof(PVOID))) {
+          TI_DbgPrint(MID_TRACE, ("MDL buffer too small (ptr).\n"));
+          return STATUS_BUFFER_TOO_SMALL;
+        }
+
         AddressInfo = (PTDI_CONNECTION_INFORMATION)
           MmGetSystemAddressForMdl(Irp->MdlAddress);
 
         switch ((ULONG)IrpSp->FileObject->FsContext2) {
           case TDI_TRANSPORT_ADDRESS_FILE:
             AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
+            Endpoint = AddrFile ? AddrFile->Connection : NULL;
             break;
 
           case TDI_CONNECTION_FILE:
@@ -738,14 +759,7 @@ NTSTATUS DispTdiQueryInformation(
           return STATUS_INVALID_PARAMETER;
         }
 
-        if (MmGetMdlByteCount(Irp->MdlAddress) <
-            (FIELD_OFFSET(TDI_CONNECTION_INFORMATION, RemoteAddress) +
-             sizeof(PVOID))) {
-          TI_DbgPrint(MID_TRACE, ("MDL buffer too small (ptr).\n"));
-          return STATUS_BUFFER_OVERFLOW;
-        }
-
-        return TCPGetPeerAddress( Endpoint, AddressInfo->RemoteAddress );
+        return TCPGetSockAddress( Endpoint, AddressInfo->RemoteAddress, TRUE );
       }
   }
 
@@ -767,7 +781,7 @@ NTSTATUS DispTdiReceive(
   PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
   PTRANSPORT_CONTEXT TranContext;
   NTSTATUS Status;
-  ULONG BytesReceived;
+  ULONG BytesReceived = 0;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -778,13 +792,15 @@ NTSTATUS DispTdiReceive(
   if (TranContext == NULL)
     {
       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-      return STATUS_INVALID_CONNECTION;
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
     }
 
   if (TranContext->Handle.ConnectionContext == NULL)
     {
       TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
-      return STATUS_INVALID_CONNECTION;
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
     }
 
   /* Initialize a receive request */
@@ -804,13 +820,14 @@ NTSTATUS DispTdiReceive(
          ReceiveInfo->ReceiveFlags,
          DispDataRequestComplete,
          Irp);
-      if (Status != STATUS_PENDING)
-      {
-          DispDataRequestComplete(Irp, Status, BytesReceived);
-      } else
-         IoMarkIrpPending(Irp);
     }
 
+done:
+  if (Status != STATUS_PENDING) {
+      DispDataRequestComplete(Irp, Status, BytesReceived);
+  } else
+      IoMarkIrpPending(Irp);
+
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
 
   return Status;
@@ -832,7 +849,7 @@ NTSTATUS DispTdiReceiveDatagram(
   PTRANSPORT_CONTEXT TranContext;
   TDI_REQUEST Request;
   NTSTATUS Status;
-  ULONG BytesReceived;
+  ULONG BytesReceived = 0;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -843,7 +860,8 @@ NTSTATUS DispTdiReceiveDatagram(
   if (TranContext == NULL)
     {
       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-      return STATUS_INVALID_ADDRESS;
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
     }
 
   /* Initialize a receive request */
@@ -858,14 +876,14 @@ NTSTATUS DispTdiReceiveDatagram(
 
   if (NT_SUCCESS(Status))
     {
-       PCHAR DataBuffer;
+       PVOID DataBuffer;
        UINT BufferSize;
 
        NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
                         &DataBuffer,
                         &BufferSize );
 
-      Status = UDPReceiveDatagram(
+      Status = DGReceiveDatagram(
          Request.Handle.AddressHandle,
          DgramInfo->ReceiveDatagramInformation,
          DataBuffer,
@@ -874,13 +892,16 @@ NTSTATUS DispTdiReceiveDatagram(
          DgramInfo->ReturnDatagramInformation,
          &BytesReceived,
          (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete,
-         Irp);
-      if (Status != STATUS_PENDING) {
-          DispDataRequestComplete(Irp, Status, BytesReceived);
-      } else
-         IoMarkIrpPending(Irp);
+         Irp,
+          Irp);
     }
 
+done:
+   if (Status != STATUS_PENDING) {
+       DispDataRequestComplete(Irp, Status, BytesReceived);
+   } else
+       IoMarkIrpPending(Irp);
+
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
 
   return Status;
@@ -901,7 +922,7 @@ NTSTATUS DispTdiSend(
   PTDI_REQUEST_KERNEL_SEND SendInfo;
   PTRANSPORT_CONTEXT TranContext;
   NTSTATUS Status;
-  ULONG BytesSent;
+  ULONG BytesSent = 0;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -912,13 +933,15 @@ NTSTATUS DispTdiSend(
   if (TranContext == NULL)
     {
       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-      return STATUS_INVALID_CONNECTION;
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
     }
 
   if (TranContext->Handle.ConnectionContext == NULL)
     {
       TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
-      return STATUS_INVALID_CONNECTION;
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
     }
 
   Status = DispPrepareIrpForCancel(
@@ -929,7 +952,7 @@ NTSTATUS DispTdiSend(
   TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
   if (NT_SUCCESS(Status))
     {
-       PCHAR Data;
+       PVOID Data;
        UINT Len;
 
        NdisQueryBuffer( Irp->MdlAddress, &Data, &Len );
@@ -943,13 +966,14 @@ NTSTATUS DispTdiSend(
            SendInfo->SendFlags,
            DispDataRequestComplete,
            Irp);
-       if (Status != STATUS_PENDING)
-       {
-           DispDataRequestComplete(Irp, Status, BytesSent);
-       } else
-           IoMarkIrpPending( Irp );
     }
 
+done:
+   if (Status != STATUS_PENDING) {
+       DispDataRequestComplete(Irp, Status, BytesSent);
+   } else
+       IoMarkIrpPending(Irp);
+
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
 
   return Status;
@@ -976,7 +1000,14 @@ NTSTATUS DispTdiSendDatagram(
 
     IrpSp       = IoGetCurrentIrpStackLocation(Irp);
     DgramInfo   = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters);
+
     TranContext = IrpSp->FileObject->FsContext;
+    if (TranContext == NULL)
+    {
+      TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
+      Status = STATUS_INVALID_PARAMETER;
+      goto done;
+    }
 
     /* Initialize a send request */
     Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
@@ -989,7 +1020,7 @@ NTSTATUS DispTdiSendDatagram(
         (PDRIVER_CANCEL)DispCancelRequest);
 
     if (NT_SUCCESS(Status)) {
-       PCHAR DataBuffer;
+       PVOID DataBuffer;
        UINT BufferSize;
 
        TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress));
@@ -1004,25 +1035,25 @@ NTSTATUS DispTdiSendDatagram(
                    ("About to call send routine %x\n",
                     (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)));
 
-        if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send) )
+        if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send != NULL) )
             Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
                 Request.Handle.AddressHandle,
                 DgramInfo->SendDatagramInformation,
                 DataBuffer,
                 BufferSize,
                 &Irp->IoStatus.Information);
-        else
+        else {
             Status = STATUS_UNSUCCESSFUL;
-
-        if (Status != STATUS_PENDING) {
-            DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
-            /* Return STATUS_PENDING because DispPrepareIrpForCancel
-               marks Irp as pending */
-            Status = STATUS_PENDING;
-        } else
-           IoMarkIrpPending( Irp );
+            ASSERT(FALSE);
+        }
     }
 
+done:
+    if (Status != STATUS_PENDING) {
+        DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
+    } else
+        IoMarkIrpPending(Irp);
+
     TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
 
     return Status;
@@ -1066,7 +1097,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
   Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
   Status     = STATUS_SUCCESS;
 
-  TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+  KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
 
   /* Set the event handler. if an event handler is associated with
      a specific event, it's flag (RegisteredXxxHandler) is TRUE.
@@ -1187,7 +1218,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
     Status = STATUS_INVALID_PARAMETER;
   }
 
-  TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+  KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
 
   return Status;
 }
@@ -1222,11 +1253,10 @@ VOID DispTdiQueryInformationExComplete(
  */
 {
     PTI_QUERY_CONTEXT QueryContext;
-    UINT Count = 0;
 
     QueryContext = (PTI_QUERY_CONTEXT)Context;
     if (NT_SUCCESS(Status)) {
-        Count = CopyBufferToBufferChain(
+        CopyBufferToBufferChain(
             QueryContext->InputMdl,
             FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
             (PCHAR)&QueryContext->QueryInfo.Context,
@@ -1243,7 +1273,7 @@ VOID DispTdiQueryInformationExComplete(
     QueryContext->Irp->IoStatus.Information = ByteCount;
     QueryContext->Irp->IoStatus.Status      = Status;
 
-    ExFreePool(QueryContext);
+    ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
 }
 
 
@@ -1306,9 +1336,9 @@ NTSTATUS DispTdiQueryInformationEx(
             IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
         OutputBuffer = Irp->UserBuffer;
 
-        QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
+        QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
         if (QueryContext) {
-           _SEH_TRY {
+           _SEH2_TRY {
                 InputMdl = IoAllocateMdl(InputBuffer,
                     sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
                     FALSE, TRUE, NULL);
@@ -1332,9 +1362,9 @@ NTSTATUS DispTdiQueryInformationEx(
                         InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
                 } else
                     Status = STATUS_INSUFFICIENT_RESOURCES;
-            } _SEH_HANDLE {
-                Status = _SEH_GetExceptionCode();
-            } _SEH_END;
+            } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+                Status = _SEH2_GetExceptionCode();
+            } _SEH2_END;
 
             if (NT_SUCCESS(Status)) {
                 Size = MmGetMdlByteCount(OutputMdl);
@@ -1369,7 +1399,7 @@ NTSTATUS DispTdiQueryInformationEx(
                 IoFreeMdl(OutputMdl);
             }
 
-            ExFreePool(QueryContext);
+            ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
         } else
             Status = STATUS_INSUFFICIENT_RESOURCES;
     } else if( InputBufferLength ==
@@ -1382,10 +1412,10 @@ NTSTATUS DispTdiQueryInformationEx(
 
        Size = 0;
 
-        QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
+        QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
         if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
 
-       _SEH_TRY {
+       _SEH2_TRY {
            InputMdl = IoAllocateMdl(InputBuffer,
                                     sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
                                     FALSE, TRUE, NULL);
@@ -1395,14 +1425,14 @@ NTSTATUS DispTdiQueryInformationEx(
 
            InputMdlLocked = TRUE;
            Status = STATUS_SUCCESS;
-       } _SEH_HANDLE {
+       } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
            TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
-           Status = _SEH_GetExceptionCode();
-       } _SEH_END;
+           Status = _SEH2_GetExceptionCode();
+       } _SEH2_END;
 
        if( !NT_SUCCESS(Status) || !InputMdl ) {
            if( InputMdl ) IoFreeMdl( InputMdl );
-           ExFreePool(QueryContext);
+           ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
            return Status;
        }
 
@@ -1446,7 +1476,6 @@ NTSTATUS DispTdiSetInformationEx(
     PTCP_REQUEST_SET_INFORMATION_EX Info;
     TDI_REQUEST Request;
     TDI_STATUS Status;
-    KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -1472,7 +1501,7 @@ NTSTATUS DispTdiSetInformationEx(
 
         TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
 
-        return IRPFinish(Irp, STATUS_INVALID_PARAMETER);
+        return Irp->IoStatus.Status;
     }
 
     Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
@@ -1482,12 +1511,6 @@ NTSTATUS DispTdiSetInformationEx(
 
         Status = InfoTdiSetInformationEx(&Request, &Info->ID,
             &Info->Buffer, Info->BufferSize);
-
-        if (Status != STATUS_PENDING) {
-            IoAcquireCancelSpinLock(&OldIrql);
-            (void)IoSetCancelRoutine(Irp, NULL);
-            IoReleaseCancelSpinLock(OldIrql);
-        }
     }
 
     return Status;
@@ -1505,7 +1528,7 @@ NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
         (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
     IF_LIST_ITER(IF);
 
-    TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n", 
+    TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
                           IpAddrChange->NteIndex));
 
     ForEachInterface(IF) {
@@ -1522,6 +1545,10 @@ NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
             IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
             IF->Netmask.Type = IP_ADDRESS_V4;
             IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
+            IF->Broadcast.Type = IP_ADDRESS_V4;
+           IF->Broadcast.Address.IPv4Address =
+               IF->Unicast.Address.IPv4Address |
+               ~IF->Netmask.Address.IPv4Address;
 
             TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
                                    IF->Unicast.Address.IPv4Address));
@@ -1548,10 +1575,13 @@ NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
 
     ForEachInterface(IF) {
         if( IF->Index == *NteIndex ) {
+            IPRemoveInterfaceRoute( IF );
             IF->Unicast.Type = IP_ADDRESS_V4;
             IF->Unicast.Address.IPv4Address = 0;
             IF->Netmask.Type = IP_ADDRESS_V4;
             IF->Netmask.Address.IPv4Address = 0;
+            IF->Broadcast.Type = IP_ADDRESS_V4;
+            IF->Broadcast.Address.IPv4Address = 0;
             Status = STATUS_SUCCESS;
         }
     } EndFor(IF);