[TCPIP]
[reactos.git] / reactos / drivers / network / tcpip / tcpip / main.c
index f8aa222..034b9df 100644 (file)
@@ -24,8 +24,6 @@ UDP_STATISTICS UDPStats;
 /* Network timers */
 KTIMER IPTimer;
 KDPC IPTimeoutDpc;
-KSPIN_LOCK IpWorkLock;
-WORK_QUEUE_ITEM IpWorkItem;
 
 VOID TiWriteErrorLog(
     PDRIVER_OBJECT DriverContext,
@@ -107,149 +105,161 @@ NTSTATUS TiCreateFileObject(
   PDEVICE_OBJECT DeviceObject,
   PIRP Irp)
 {
-  PFILE_FULL_EA_INFORMATION EaInfo;
-  PTRANSPORT_CONTEXT Context;
-  PIO_STACK_LOCATION IrpSp;
-  PTA_IP_ADDRESS Address;
-  TDI_REQUEST Request;
-  PVOID ClientContext;
-  NTSTATUS Status;
-  ULONG Protocol;
-
-  TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
-
-  EaInfo = Irp->AssociatedIrp.SystemBuffer;
-CP
-  /* Parameter check */
-  /* No EA information means that we're opening for SET/QUERY_INFORMATION
-   * style calls. */
-#if 0
-  if (!EaInfo) {
-    TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
-    return STATUS_INVALID_PARAMETER;
-  }
-#endif
-CP
-  /* Allocate resources here. We release them again if something failed */
-  Context = exAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT));
-  if (!Context) {
-    TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-    return STATUS_INSUFFICIENT_RESOURCES;
-  }
-CP
-  Context->CancelIrps = FALSE;
-CP
-  IrpSp = IoGetCurrentIrpStackLocation(Irp);
-  IrpSp->FileObject->FsContext = Context;
-  Request.RequestContext       = Irp;
-CP
-  /* Branch to the right handler */
-  if (EaInfo &&
-      (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
-      (RtlCompareMemory
-       (&EaInfo->EaName, TdiTransportAddress,
-       TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
-    /* This is a request to open an address */
-CP
-
-       /* XXX This should probably be done in IoCreateFile() */
-    /* Parameter checks */
-
-    Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term
-
-    if ((EaInfo->EaValueLength < sizeof(TA_IP_ADDRESS)) ||
-      (Address->TAAddressCount != 1) ||
-      (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
-      (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP)) {
-      TI_DbgPrint(MIN_TRACE, ("Parameters are invalid:\n"));
-      TI_DbgPrint(MIN_TRACE, ("AddressCount: %d\n", Address->TAAddressCount));
-      if( Address->TAAddressCount == 1 ) {
-         TI_DbgPrint(MIN_TRACE, ("AddressLength: %\n",
-                                 Address->Address[0].AddressLength));
-         TI_DbgPrint(MIN_TRACE, ("AddressType: %\n",
-                                 Address->Address[0].AddressType));
-      }
-      exFreePool(Context);
-      return STATUS_INVALID_PARAMETER;
-    }
-CP
-    /* Open address file object */
-
-    /* Protocol depends on device object so find the protocol */
-    if (DeviceObject == TCPDeviceObject)
-      Protocol = IPPROTO_TCP;
-    else if (DeviceObject == UDPDeviceObject)
-      Protocol = IPPROTO_UDP;
-    else if (DeviceObject == IPDeviceObject)
-      Protocol = IPPROTO_RAW;
-    else if (DeviceObject == RawIPDeviceObject) {
-      Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
-      if (!NT_SUCCESS(Status)) {
-        TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
-        exFreePool(Context);
-        return STATUS_INVALID_PARAMETER;
-      }
-    } else {
-      TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
-      exFreePool(Context);
-      return STATUS_INVALID_PARAMETER;
-    }
-CP
-    Status = FileOpenAddress(&Request, Address, Protocol, NULL);
-    if (NT_SUCCESS(Status)) {
-      IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
-      Context->Handle.AddressHandle = Request.Handle.AddressHandle;
-    }
-CP
-  } else if (EaInfo &&
-            (EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
-            (RtlCompareMemory
-             (&EaInfo->EaName, TdiConnectionContext,
-              TDI_CONNECTION_CONTEXT_LENGTH) ==
-             TDI_CONNECTION_CONTEXT_LENGTH)) {
-    /* This is a request to open a connection endpoint */
-CP
-    /* Parameter checks */
-
-    if (EaInfo->EaValueLength < sizeof(PVOID)) {
-      TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
-      exFreePool(Context);
-      return STATUS_INVALID_PARAMETER;
+    PFILE_FULL_EA_INFORMATION EaInfo;
+    PTRANSPORT_CONTEXT Context;
+    PIO_STACK_LOCATION IrpSp;
+    PTA_IP_ADDRESS Address;
+    TDI_REQUEST Request;
+    PVOID ClientContext;
+    NTSTATUS Status;
+    ULONG Protocol;
+
+    TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
+
+    EaInfo = Irp->AssociatedIrp.SystemBuffer;
+
+    /* Parameter check */
+    /* No EA information means that we're opening for SET/QUERY_INFORMATION
+    * style calls. */
+
+    /* Allocate resources here. We release them again if something failed */
+    Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSPORT_CONTEXT),
+                                    TRANS_CONTEXT_TAG);
+    if (!Context)
+    {
+        TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    /* Can only do connection oriented communication using TCP */
+    Context->CancelIrps = FALSE;
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    IrpSp->FileObject->FsContext = Context;
+    Request.RequestContext       = Irp;
+
+    /* Branch to the right handler */
+    if (EaInfo &&
+        (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
+        (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress,
+        TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH))
+    {
+        /* This is a request to open an address */
+
+
+        /* XXX This should probably be done in IoCreateFile() */
+        /* Parameter checks */
+
+        Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term
+
+        if ((EaInfo->EaValueLength < sizeof(TA_IP_ADDRESS)) ||
+            (Address->TAAddressCount != 1) ||
+            (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
+            (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP))
+        {
+            TI_DbgPrint(MIN_TRACE, ("Parameters are invalid:\n"));
+            TI_DbgPrint(MIN_TRACE, ("AddressCount: %d\n", Address->TAAddressCount));
+            if( Address->TAAddressCount == 1 )
+            {
+                   TI_DbgPrint(MIN_TRACE, ("AddressLength: %\n",
+                                           Address->Address[0].AddressLength));
+                   TI_DbgPrint(MIN_TRACE, ("AddressType: %\n",
+                                           Address->Address[0].AddressType));
+            }
+
+            ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Open address file object */
+
+        /* Protocol depends on device object so find the protocol */
+        if (DeviceObject == TCPDeviceObject)
+            Protocol = IPPROTO_TCP;
+        else if (DeviceObject == UDPDeviceObject)
+            Protocol = IPPROTO_UDP;
+        else if (DeviceObject == IPDeviceObject)
+            Protocol = IPPROTO_RAW;
+        else if (DeviceObject == RawIPDeviceObject)
+        {
+            Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
+            if (!NT_SUCCESS(Status))
+            {
+                TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
+                ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
+                return STATUS_INVALID_PARAMETER;
+            }
+        }
+        else
+        {
+            TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
+            ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        Status = FileOpenAddress(&Request, Address, Protocol, NULL);
+        if (NT_SUCCESS(Status))
+        {
+            IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
+            Context->Handle.AddressHandle = Request.Handle.AddressHandle;
+        }
 
-    if (DeviceObject != TCPDeviceObject) {
-      TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
-      exFreePool(Context);
-      return STATUS_INVALID_PARAMETER;
     }
-
-    ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
-
-    /* Open connection endpoint file object */
-
-    Status = FileOpenConnection(&Request, ClientContext);
-    if (NT_SUCCESS(Status)) {
-      IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
-      Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
+    else if (EaInfo &&
+               (EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
+               (RtlCompareMemory
+               (&EaInfo->EaName, TdiConnectionContext,
+               TDI_CONNECTION_CONTEXT_LENGTH) ==
+               TDI_CONNECTION_CONTEXT_LENGTH))
+    {
+        /* This is a request to open a connection endpoint */
+
+        /* Parameter checks */
+
+        if (EaInfo->EaValueLength < sizeof(PVOID))
+        {
+            TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
+            ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Can only do connection oriented communication using TCP */
+
+        if (DeviceObject != TCPDeviceObject)
+        {
+            TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
+            ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
+
+        /* Open connection endpoint file object */
+
+        Status = FileOpenConnection(&Request, ClientContext);
+        if (NT_SUCCESS(Status))
+        {
+            IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
+            Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
+        }
     }
-  } else {
-    /* This is a request to open a control connection */
-    Status = FileOpenControlChannel(&Request);
-    if (NT_SUCCESS(Status)) {
-      IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
-      Context->Handle.ControlChannel = Request.Handle.ControlChannel;
+    else
+    {
+        /* This is a request to open a control connection */
+        Status = FileOpenControlChannel(&Request);
+        if (NT_SUCCESS(Status))
+        {
+            IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
+            Context->Handle.ControlChannel = Request.Handle.ControlChannel;
+        }
     }
-  }
 
-  if (!NT_SUCCESS(Status))
-    exFreePool(Context);
+    if (!NT_SUCCESS(Status))
+        ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
 
-  TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
+    TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
 
-  Irp->IoStatus.Status = Status;
-  return Status;
+    Irp->IoStatus.Status = Status;
+    return Status;
 }
 
 
@@ -267,43 +277,44 @@ NTSTATUS TiCloseFileObject(
   PDEVICE_OBJECT DeviceObject,
   PIRP Irp)
 {
-  PIO_STACK_LOCATION IrpSp;
-  PTRANSPORT_CONTEXT Context;
-  TDI_REQUEST Request;
-  NTSTATUS Status;
-
-  IrpSp   = IoGetCurrentIrpStackLocation(Irp);
-  Context = IrpSp->FileObject->FsContext;
-  if (!Context) {
-    TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
-    return STATUS_INVALID_PARAMETER;
-  }
-
-  switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
-  case TDI_TRANSPORT_ADDRESS_FILE:
-    Request.Handle.AddressHandle = Context->Handle.AddressHandle;
-    Status = FileCloseAddress(&Request);
-    break;
-
-  case TDI_CONNECTION_FILE:
-    Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
-    Status = FileCloseConnection(&Request);
-    break;
-
-  case TDI_CONTROL_CHANNEL_FILE:
-    Request.Handle.ControlChannel = Context->Handle.ControlChannel;
-    Status = FileCloseControlChannel(&Request);
-    break;
+    PIO_STACK_LOCATION IrpSp;
+    PTRANSPORT_CONTEXT Context;
+    TDI_REQUEST Request;
+    NTSTATUS Status;
+
+    IrpSp   = IoGetCurrentIrpStackLocation(Irp);
+    Context = IrpSp->FileObject->FsContext;
+    if (!Context)
+    {
+        TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
 
-  default:
-    DbgPrint("Unknown type %d\n", (ULONG_PTR)IrpSp->FileObject->FsContext2);
-    Status = STATUS_INVALID_PARAMETER;
-    break;
-  }
+    switch ((ULONG_PTR)IrpSp->FileObject->FsContext2)
+    {
+        case TDI_TRANSPORT_ADDRESS_FILE:
+            Request.Handle.AddressHandle = Context->Handle.AddressHandle;
+            Status = FileCloseAddress(&Request);
+            break;
+
+        case TDI_CONNECTION_FILE:
+            Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
+            Status = FileCloseConnection(&Request);
+            break;
+
+        case TDI_CONTROL_CHANNEL_FILE:
+            Request.Handle.ControlChannel = Context->Handle.ControlChannel;
+            Status = FileCloseControlChannel(&Request);
+            break;
+
+        default:
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+    }
 
-  Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Status = Status;
 
-  return Irp->IoStatus.Status;
+    return Irp->IoStatus.Status;
 }
 
 
@@ -322,9 +333,6 @@ TiDispatchOpenClose(
 {
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status;
-  PTRANSPORT_CONTEXT Context;
-
-  IRPRemember(Irp, __FILE__, __LINE__);
 
 //  DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
 
@@ -338,8 +346,7 @@ TiDispatchOpenClose(
 
   /* Close an address file, connection endpoint, or control connection */
   case IRP_MJ_CLOSE:
-    Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
-       Status = TiCloseFileObject(DeviceObject, Irp);
+    Status = TiCloseFileObject(DeviceObject, Irp);
     break;
 
   default:
@@ -369,11 +376,9 @@ TiDispatchInternal(
   BOOLEAN Complete = TRUE;
   PIO_STACK_LOCATION IrpSp;
 
-  IRPRemember(Irp, __FILE__, __LINE__);
-
   IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
-  TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
+  TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
     DeviceObject, Irp, IrpSp->MinorFunction));
 
   Irp->IoStatus.Status      = STATUS_SUCCESS;
@@ -448,7 +453,7 @@ TiDispatchInternal(
     Status = STATUS_INVALID_DEVICE_REQUEST;
   }
 
-  TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
+  TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status));
 
   if( Complete )
       IRPFinish( Irp, Status );
@@ -473,11 +478,9 @@ TiDispatch(
   NTSTATUS Status;
   PIO_STACK_LOCATION IrpSp;
 
-  IRPRemember(Irp, __FILE__, __LINE__);
-
   IrpSp  = IoGetCurrentIrpStackLocation(Irp);
 
-  TI_DbgPrint(DEBUG_IRP, ("Called. IRP is at (0x%X).\n", Irp));
+  TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp));
 
   Irp->IoStatus.Information = 0;
 
@@ -520,7 +523,7 @@ TiDispatch(
     }
   }
 
-  TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
+  TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status));
 
   return IRPFinish( Irp, Status );
 }
@@ -539,12 +542,10 @@ VOID NTAPI TiUnload(
 
   TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
   if (!IsListEmpty(&AddressFileListHead)) {
-    TI_DbgPrint(MIN_TRACE, ("Open address file objects exists.\n"));
+    TI_DbgPrint(MIN_TRACE, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
   }
   TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
 #endif
-  ChewShutdown();
-
   /* Cancel timer */
   KeCancelTimer(&IPTimer);
 
@@ -582,35 +583,15 @@ VOID NTAPI TiUnload(
   if (RawIPDeviceObject)
     IoDeleteDevice(RawIPDeviceObject);
 
-  if (IPDeviceObject)
-    IoDeleteDevice(IPDeviceObject);
+  if (IPDeviceObject) {
+     ChewShutdown();
+     IoDeleteDevice(IPDeviceObject);
+  }
 
   if (EntityList)
-    exFreePool(EntityList);
+    ExFreePoolWithTag(EntityList, TDI_ENTITY_TAG);
 
-  TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
-}
-
-VOID NTAPI IPTimeoutDpcFn(
-    PKDPC Dpc,
-    PVOID DeferredContext,
-    PVOID SystemArgument1,
-    PVOID SystemArgument2)
-/*
- * FUNCTION: Timeout DPC
- * ARGUMENTS:
- *     Dpc             = Pointer to our DPC object
- *     DeferredContext = Pointer to context information (unused)
- *     SystemArgument1 = Unused
- *     SystemArgument2 = Unused
- * NOTES:
- *     This routine is dispatched once in a while to do maintainance jobs
- */
-{
-    if( !IpWorkItemQueued ) {
-       ExQueueWorkItem( &IpWorkItem, DelayedWorkQueue );
-       IpWorkItemQueued = TRUE;
-    }
+  TI_DbgPrint(MAX_TRACE, ("[TCPIP, TiUnload] Leaving.\n"));
 }
 
 NTSTATUS NTAPI
@@ -635,19 +616,23 @@ DriverEntry(
   NDIS_STATUS NdisStatus;
   LARGE_INTEGER DueTime;
 
-  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-  TrackingInit();
+  TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Called\n"));
 
   /* TdiInitialize() ? */
 
   /* FIXME: Create symbolic links in Win32 namespace */
 
+  /* Initialize our periodic timer and its associated DPC object. When the
+     timer expires, the IPTimeout deferred procedure call (DPC) is queued */
+  KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
+  KeInitializeTimer(&IPTimer);
+
   /* Create IP device object */
   Status = IoCreateDevice(DriverObject, 0, &strIpDeviceName,
     FILE_DEVICE_NETWORK, 0, FALSE, &IPDeviceObject);
   if (!NT_SUCCESS(Status)) {
     TI_DbgPrint(MIN_TRACE, ("Failed to create IP device object. Status (0x%X).\n", Status));
+    TiUnload(DriverObject);
     return Status;
   }
 
@@ -658,8 +643,7 @@ DriverEntry(
     FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);
   if (!NT_SUCCESS(Status)) {
     TI_DbgPrint(MIN_TRACE, ("Failed to create RawIP device object. Status (0x%X).\n", Status));
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
+    TiUnload(DriverObject);
     return Status;
   }
 
@@ -668,9 +652,7 @@ DriverEntry(
     FILE_DEVICE_NETWORK, 0, FALSE, &UDPDeviceObject);
   if (!NT_SUCCESS(Status)) {
     TI_DbgPrint(MIN_TRACE, ("Failed to create UDP device object. Status (0x%X).\n", Status));
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
-    IoDeleteDevice(RawIPDeviceObject);
+    TiUnload(DriverObject);
     return Status;
   }
 
@@ -679,23 +661,18 @@ DriverEntry(
     FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject);
   if (!NT_SUCCESS(Status)) {
     TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status));
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
-    IoDeleteDevice(RawIPDeviceObject);
-    IoDeleteDevice(UDPDeviceObject);
+    TiUnload(DriverObject);
     return Status;
   }
 
   /* Setup network layer and transport layer entities */
   KeInitializeSpinLock(&EntityListLock);
-  EntityList = exAllocatePool(NonPagedPool, sizeof(TDIEntityID) * MAX_TDI_ENTITIES );
+  EntityList = ExAllocatePoolWithTag(NonPagedPool,
+                                     sizeof(TDIEntityID) * MAX_TDI_ENTITIES,
+                                     TDI_ENTITY_TAG );
   if (!EntityList) {
     TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
-    IoDeleteDevice(RawIPDeviceObject);
-    IoDeleteDevice(UDPDeviceObject);
-    IoDeleteDevice(TCPDeviceObject);
+    TiUnload(DriverObject);
     return STATUS_INSUFFICIENT_RESOURCES;
   }
 
@@ -703,27 +680,16 @@ DriverEntry(
   EntityMax   = MAX_TDI_ENTITIES;
 
   /* Allocate NDIS packet descriptors */
-  NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT));
+  NdisAllocatePacketPoolEx(&NdisStatus, &GlobalPacketPool, 500, 1500, sizeof(PACKET_CONTEXT));
   if (NdisStatus != NDIS_STATUS_SUCCESS) {
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
-    IoDeleteDevice(RawIPDeviceObject);
-    IoDeleteDevice(UDPDeviceObject);
-    IoDeleteDevice(TCPDeviceObject);
-    exFreePool(EntityList);
+    TiUnload(DriverObject);
     return STATUS_INSUFFICIENT_RESOURCES;
   }
 
   /* Allocate NDIS buffer descriptors */
-  NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 100);
+  NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 2000);
   if (NdisStatus != NDIS_STATUS_SUCCESS) {
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
-    IoDeleteDevice(RawIPDeviceObject);
-    IoDeleteDevice(UDPDeviceObject);
-    IoDeleteDevice(TCPDeviceObject);
-    exFreePool(EntityList);
-    NdisFreePacketPool(GlobalPacketPool);
+    TiUnload(DriverObject);
     return STATUS_INSUFFICIENT_RESOURCES;
   }
 
@@ -745,64 +711,26 @@ DriverEntry(
   /* Initialize transport level protocol subsystems */
   Status = RawIPStartup();
   if( !NT_SUCCESS(Status) ) {
-        IPShutdown();
-        ChewShutdown();
-        IoDeleteDevice(IPDeviceObject);
-        IoDeleteDevice(RawIPDeviceObject);
-        IoDeleteDevice(UDPDeviceObject);
-        IoDeleteDevice(TCPDeviceObject);
-        exFreePool(EntityList);
-        NdisFreePacketPool(GlobalPacketPool);
-        NdisFreeBufferPool(GlobalBufferPool);
-       return Status;
+      TiUnload(DriverObject);
+      return Status;
   }
 
   Status = UDPStartup();
   if( !NT_SUCCESS(Status) ) {
-        RawIPShutdown();
-        IPShutdown();
-        ChewShutdown();
-        IoDeleteDevice(IPDeviceObject);
-        IoDeleteDevice(RawIPDeviceObject);
-        IoDeleteDevice(UDPDeviceObject);
-        IoDeleteDevice(TCPDeviceObject);
-        exFreePool(EntityList);
-        NdisFreePacketPool(GlobalPacketPool);
-        NdisFreeBufferPool(GlobalBufferPool);
-       return Status;
+      TiUnload(DriverObject);
+      return Status;
   }
 
   Status = TCPStartup();
   if( !NT_SUCCESS(Status) ) {
-        UDPShutdown();
-        RawIPShutdown();
-        IPShutdown();
-        ChewShutdown();
-        IoDeleteDevice(IPDeviceObject);
-        IoDeleteDevice(RawIPDeviceObject);
-        IoDeleteDevice(UDPDeviceObject);
-        IoDeleteDevice(TCPDeviceObject);
-        exFreePool(EntityList);
-        NdisFreePacketPool(GlobalPacketPool);
-        NdisFreeBufferPool(GlobalBufferPool);
-       return Status;
+      TiUnload(DriverObject);
+      return Status;
   }
 
   Status = ICMPStartup();
   if( !NT_SUCCESS(Status) ) {
-        TCPShutdown();
-        UDPShutdown();
-        RawIPShutdown();
-        IPShutdown();
-        ChewShutdown();
-        IoDeleteDevice(IPDeviceObject);
-        IoDeleteDevice(RawIPDeviceObject);
-        IoDeleteDevice(UDPDeviceObject);
-        IoDeleteDevice(TCPDeviceObject);
-        exFreePool(EntityList);
-        NdisFreePacketPool(GlobalPacketPool);
-        NdisFreeBufferPool(GlobalBufferPool);
-       return Status;
+      TiUnload(DriverObject);
+      return Status;
   }
 
   /* Use direct I/O */
@@ -819,33 +747,11 @@ DriverEntry(
 
   DriverObject->DriverUnload = TiUnload;
 
-  /* Initialize our periodic timer and its associated DPC object. When the
-     timer expires, the IPTimeout deferred procedure call (DPC) is queued */
-  ExInitializeWorkItem( &IpWorkItem, IPTimeout, NULL );
-  KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
-  KeInitializeTimer(&IPTimer);
-
-  /* Start the periodic timer with an initial and periodic
-     relative expiration time of IP_TIMEOUT milliseconds */
-  DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000;
-  KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc);
-
   /* Open loopback adapter */
   Status = LoopRegisterAdapter(NULL, NULL);
   if (!NT_SUCCESS(Status)) {
     TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
-    TCPShutdown();
-    UDPShutdown();
-    RawIPShutdown();
-    IPShutdown();
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
-    IoDeleteDevice(RawIPDeviceObject);
-    IoDeleteDevice(UDPDeviceObject);
-    IoDeleteDevice(TCPDeviceObject);
-    exFreePool(EntityList);
-    NdisFreePacketPool(GlobalPacketPool);
-    NdisFreeBufferPool(GlobalBufferPool);
+    TiUnload(DriverObject);
     return Status;
   }
 
@@ -862,25 +768,21 @@ DriverEntry(
       NULL,
       0,
       NULL);
-    TCPShutdown();
-    UDPShutdown();
-    RawIPShutdown();
-    IPShutdown();
-    ChewShutdown();
-    IoDeleteDevice(IPDeviceObject);
-    IoDeleteDevice(RawIPDeviceObject);
-    IoDeleteDevice(UDPDeviceObject);
-    IoDeleteDevice(TCPDeviceObject);
-    exFreePool(EntityList);
-    NdisFreePacketPool(GlobalPacketPool);
-    NdisFreeBufferPool(GlobalBufferPool);
-    return Status;
+      TiUnload(DriverObject);
+      return Status;
   }
 
+  /* Start the periodic timer with an initial and periodic
+     relative expiration time of IP_TIMEOUT milliseconds */
+  DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000;
+  KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc);
+
+  TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Finished\n"));
+
+
   return STATUS_SUCCESS;
 }
 
-
 VOID NTAPI
 IPAddInterface(
        ULONG   Unknown0,