- Silence TCPIP.
[reactos.git] / reactos / drivers / net / tcpip / tcpip / main.c
index 6f9b55c..b5a49e2 100644 (file)
@@ -7,19 +7,15 @@
  * REVISIONS:
  *   CSH 01/08-2000 Created
  */
-#include <tcpip.h>
-#include <dispatch.h>
-#include <fileobjs.h>
-#include <datagram.h>
-#include <loopback.h>
-#include <rawip.h>
-#include <udp.h>
-#include <tcp.h>
-#include <rosrtl/string.h>
+#include "precomp.h"
 
-#ifdef DBG
-DWORD DebugTraceLevel = MIN_TRACE;
-#endif /* DBG */
+#define NDEBUG
+
+#ifndef NDEBUG
+DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER);
+#else
+DWORD DebugTraceLevel = 0;
+#endif /* NDEBUG */
 
 PDEVICE_OBJECT TCPDeviceObject   = NULL;
 PDEVICE_OBJECT UDPDeviceObject   = NULL;
@@ -27,10 +23,23 @@ PDEVICE_OBJECT IPDeviceObject    = NULL;
 PDEVICE_OBJECT RawIPDeviceObject = NULL;
 NDIS_HANDLE GlobalPacketPool     = NULL;
 NDIS_HANDLE GlobalBufferPool     = NULL;
-TDIEntityID *EntityList          = NULL;
+KSPIN_LOCK EntityListLock;
+TDIEntityInfo *EntityList        = NULL;
 ULONG EntityCount                = 0;
+ULONG EntityMax                  = 0;
 UDP_STATISTICS UDPStats;
 
+/* Network timers */
+KTIMER IPTimer;
+KDPC IPTimeoutDpc;
+KSPIN_LOCK IpWorkLock;
+WORK_QUEUE_ITEM IpWorkItem;
+
+/* Cancel Queue */
+LIST_ENTRY CancelQueue;
+KSPIN_LOCK CancelQueueLock;
+WORK_QUEUE_ITEM CancelQueueWork;
+extern VOID DDKAPI CancelQueuePassiveHandler( PVOID Context );
 
 VOID TiWriteErrorLog(
     PDRIVER_OBJECT DriverContext,
@@ -47,7 +56,8 @@ VOID TiWriteErrorLog(
  *     ErrorCode        = An error code to put in the log entry
  *     UniqueErrorValue = UniqueErrorValue in the error log packet
  *     FinalStatus      = FinalStatus in the error log packet
- *     String           = If not NULL, a pointer to a string to put in log entry
+ *     String           = If not NULL, a pointer to a string to put in log
+ *                        entry
  *     DumpDataCount    = Number of ULONGs of dump data
  *     DumpData         = Pointer to dump data for the log entry
  */
@@ -59,7 +69,7 @@ VOID TiWriteErrorLog(
     PUCHAR pString;
     static WCHAR DriverName[] = L"TCP/IP";
 
-    EntrySize = sizeof(IO_ERROR_LOG_PACKET) + 
+    EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
         (DumpDataCount * sizeof(ULONG)) + sizeof(DriverName);
 
     if (String) {
@@ -98,46 +108,6 @@ VOID TiWriteErrorLog(
 #endif
 }
 
-
-NTSTATUS TiGetProtocolNumber(
-  PUNICODE_STRING FileName,
-  PULONG Protocol)
-/*
- * FUNCTION: Returns the protocol number from a file name
- * ARGUMENTS:
- *     FileName = Pointer to string with file name
- *     Protocol = Pointer to buffer to put protocol number in
- * RETURNS:
- *     Status of operation
- */
-{
-  UNICODE_STRING us;
-  NTSTATUS Status;
-  ULONG Value;
-  PWSTR Name;
-
-  TI_DbgPrint(MAX_TRACE, ("Called. FileName (%wZ).\n", FileName));
-
-  Name = FileName->Buffer;
-
-  if (*Name++ != (WCHAR)L'\\')
-    return STATUS_UNSUCCESSFUL;
-
-  if (*Name == (WCHAR)NULL)
-    return STATUS_UNSUCCESSFUL;
-
-  RtlInitUnicodeString(&us, Name);
-
-  Status = RtlUnicodeStringToInteger(&us, 10, &Value);
-  if (!NT_SUCCESS(Status) || ((Value > 255)))
-    return STATUS_UNSUCCESSFUL;
-
-  *Protocol = Value;
-
-  return STATUS_SUCCESS;
-}
-
-
 /*
  * FUNCTION: Creates a file object
  * ARGUMENTS:
@@ -146,6 +116,7 @@ NTSTATUS TiGetProtocolNumber(
  * RETURNS:
  *     Status of the operation
  */
+
 NTSTATUS TiCreateFileObject(
   PDEVICE_OBJECT DeviceObject,
   PIRP Irp)
@@ -164,10 +135,14 @@ NTSTATUS TiCreateFileObject(
   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));
@@ -176,7 +151,6 @@ CP
     return STATUS_INSUFFICIENT_RESOURCES;
   }
 CP
-  Context->RefCount   = 1;
   Context->CancelIrps = FALSE;
   KeInitializeEvent(&Context->CleanupEvent, NotificationEvent, FALSE);
 CP
@@ -185,21 +159,32 @@ CP
   Request.RequestContext       = Irp;
 CP
   /* Branch to the right handler */
-  if ((EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) && 
-    (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress,
-     TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
+  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"));
-      ExFreePool(Context);
+      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));
+      }
+      PoolFreeBuffer(Context);
       return STATUS_INVALID_PARAMETER;
     }
 CP
@@ -216,12 +201,12 @@ CP
       Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
       if (!NT_SUCCESS(Status)) {
         TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
-        ExFreePool(Context);
+        PoolFreeBuffer(Context);
         return STATUS_INVALID_PARAMETER;
       }
     } else {
       TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
-      ExFreePool(Context);
+      PoolFreeBuffer(Context);
       return STATUS_INVALID_PARAMETER;
     }
 CP
@@ -231,16 +216,19 @@ CP
       Context->Handle.AddressHandle = Request.Handle.AddressHandle;
     }
 CP
-  } else if ((EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) && 
-    (RtlCompareMemory(&EaInfo->EaName, TdiConnectionContext,
-     TDI_CONNECTION_CONTEXT_LENGTH) == TDI_CONNECTION_CONTEXT_LENGTH)) {
+  } 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);
+      PoolFreeBuffer(Context);
       return STATUS_INVALID_PARAMETER;
     }
 
@@ -248,7 +236,7 @@ CP
 
     if (DeviceObject != TCPDeviceObject) {
       TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
-      ExFreePool(Context);
+      PoolFreeBuffer(Context);
       return STATUS_INVALID_PARAMETER;
     }
 
@@ -263,17 +251,19 @@ CP
     }
   } else {
     /* This is a request to open a control connection */
-
-    TI_DbgPrint(MIN_TRACE, ("Control connections are not implemented yet\n"));
-
-    Status = STATUS_NOT_IMPLEMENTED;
+    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);
+    PoolFreeBuffer(Context);
 
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
 
+  Irp->IoStatus.Status = Status;
   return Status;
 }
 
@@ -298,16 +288,8 @@ VOID TiCleanupFileObjectComplete(
   TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
 
   Irp->IoStatus.Status = Status;
-  
-  IoAcquireCancelSpinLock(&OldIrql);
 
-  /* Remove the initial reference provided at object creation time */
-  TranContext->RefCount--;
-
-#ifdef DBG
-  if (TranContext->RefCount != 0)
-    TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount is %i, should be 0.\n", TranContext->RefCount));
-#endif
+  IoAcquireCancelSpinLock(&OldIrql);
 
   KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
 
@@ -336,7 +318,7 @@ NTSTATUS TiCleanupFileObject(
   KIRQL OldIrql;
 
   IrpSp   = IoGetCurrentIrpStackLocation(Irp);
-  Context = IrpSp->FileObject->FsContext;    
+  Context = IrpSp->FileObject->FsContext;
   if (!Context) {
     TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
     return STATUS_INVALID_PARAMETER;
@@ -382,18 +364,15 @@ NTSTATUS TiCleanupFileObject(
 
   if (Status != STATUS_PENDING)
     TiCleanupFileObjectComplete(Irp, Status);
-  
+
   KeWaitForSingleObject(&Context->CleanupEvent,
     UserRequest, KernelMode, FALSE, NULL);
-  
+
   return Irp->IoStatus.Status;
 }
 
 
-NTSTATUS
-#ifndef _MSC_VER
-STDCALL_FUNC
-#endif
+NTSTATUS STDCALL
 TiDispatchOpenClose(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp)
@@ -410,6 +389,8 @@ TiDispatchOpenClose(
   NTSTATUS Status;
   PTRANSPORT_CONTEXT Context;
 
+  RIRP(Irp);
+
   TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
 
   IoMarkIrpPending(Irp);
@@ -428,11 +409,11 @@ TiDispatchOpenClose(
   case IRP_MJ_CLOSE:
     Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
     if (Context)
-        ExFreePool(Context);
+        PoolFreeBuffer(Context);
     Status = STATUS_SUCCESS;
     break;
 
-  /* Release resources bound to an address file, connection endpoint, 
+  /* Release resources bound to an address file, connection endpoint,
      or control connection */
   case IRP_MJ_CLEANUP:
     Status = TiCleanupFileObject(DeviceObject, Irp);
@@ -442,18 +423,9 @@ TiDispatchOpenClose(
     Status = STATUS_INVALID_DEVICE_REQUEST;
   }
 
-  if (Status != STATUS_PENDING) {
-    IrpSp->Control &= ~SL_PENDING_RETURNED;
-    Irp->IoStatus.Status = Status;
-
-    TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
-
-    IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
-  }
-
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
 
-  return Status;
+  return IRPFinish( Irp, Status );
 }
 
 
@@ -473,9 +445,12 @@ TiDispatchInternal(
  *     Status of the operation
  */
 {
-       NTSTATUS Status;
+  NTSTATUS Status;
+  BOOL Complete = TRUE;
   PIO_STACK_LOCATION IrpSp;
 
+  RIRP(Irp);
+
   IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
   TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
@@ -487,18 +462,22 @@ TiDispatchInternal(
   switch (IrpSp->MinorFunction) {
   case TDI_RECEIVE:
     Status = DispTdiReceive(Irp);
+    Complete = FALSE;
     break;
 
   case TDI_RECEIVE_DATAGRAM:
     Status = DispTdiReceiveDatagram(Irp);
+    Complete = FALSE;
     break;
 
   case TDI_SEND:
     Status = DispTdiSend(Irp);
+    Complete = FALSE; /* Completed in DispTdiSend */
     break;
 
   case TDI_SEND_DATAGRAM:
     Status = DispTdiSendDatagram(Irp);
+    Complete = FALSE;
     break;
 
   case TDI_ACCEPT:
@@ -507,10 +486,12 @@ TiDispatchInternal(
 
   case TDI_LISTEN:
     Status = DispTdiListen(Irp);
+    Complete = FALSE;
     break;
 
   case TDI_CONNECT:
     Status = DispTdiConnect(Irp);
+    Complete = FALSE; /* Completed by the TCP event handler */
     break;
 
   case TDI_DISCONNECT:
@@ -546,17 +527,12 @@ TiDispatchInternal(
     Status = STATUS_INVALID_DEVICE_REQUEST;
   }
 
-  if (Status != STATUS_PENDING) {
-    Irp->IoStatus.Status = Status;
-
-    TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
-
-    IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
-  }
-
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
 
-       return Status;
+  if( Complete )
+      IRPFinish( Irp, Status );
+
+  return Status;
 }
 
 
@@ -579,11 +555,14 @@ TiDispatch(
   NTSTATUS Status;
   PIO_STACK_LOCATION IrpSp;
 
+  RIRP(Irp);
+
+  IrpSp  = IoGetCurrentIrpStackLocation(Irp);
+
   TI_DbgPrint(DEBUG_IRP, ("Called. IRP is at (0x%X).\n", Irp));
 
   Irp->IoStatus.Information = 0;
 
-  IrpSp  = IoGetCurrentIrpStackLocation(Irp);
 #ifdef _MSC_VER
   Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp);
   if (NT_SUCCESS(Status)) {
@@ -596,13 +575,25 @@ TiDispatch(
     /* See if this request is TCP/IP specific */
     switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
     case IOCTL_TCP_QUERY_INFORMATION_EX:
+      TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
       Status = DispTdiQueryInformationEx(Irp, IrpSp);
       break;
 
     case IOCTL_TCP_SET_INFORMATION_EX:
+      TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
       Status = DispTdiSetInformationEx(Irp, IrpSp);
       break;
 
+    case IOCTL_SET_IP_ADDRESS:
+      TI_DbgPrint(MIN_TRACE, ("SET_IP_ADDRESS\n"));
+      Status = DispTdiSetIPAddress(Irp, IrpSp);
+      break;
+
+    case IOCTL_DELETE_IP_ADDRESS:
+      TI_DbgPrint(MIN_TRACE, ("DELETE_IP_ADDRESS\n"));
+      Status = DispTdiDeleteIPAddress(Irp, IrpSp);
+      break;
+
     default:
       TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
           IrpSp->Parameters.DeviceIoControl.IoControlCode));
@@ -611,21 +602,13 @@ TiDispatch(
     }
   }
 
-  if (Status != STATUS_PENDING) {
-    Irp->IoStatus.Status = Status;
-
-    TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
-
-    IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
-  }
-
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
 
-  return Status;
+  return IRPFinish( Irp, Status );
 }
 
 
-VOID TiUnload(
+VOID STDCALL TiUnload(
   PDRIVER_OBJECT DriverObject)
 /*
  * FUNCTION: Unloads the driver
@@ -636,12 +619,14 @@ VOID TiUnload(
 #ifdef DBG
   KIRQL OldIrql;
 
-  KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
+  TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
   if (!IsListEmpty(&AddressFileListHead)) {
     TI_DbgPrint(MIN_TRACE, ("Open address file objects exists.\n"));
   }
-  KeReleaseSpinLock(&AddressFileListLock, OldIrql);
+  TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
 #endif
+  /* Cancel timer */
+  KeCancelTimer(&IPTimer);
 
   /* Unregister loopback adapter */
   LoopUnregisterAdapter(NULL);
@@ -653,11 +638,13 @@ VOID TiUnload(
   TCPShutdown();
   UDPShutdown();
   RawIPShutdown();
-  DGShutdown();
 
   /* Shutdown network level protocol subsystem */
   IPShutdown();
 
+  /* Shutdown the lan worker */
+  LANShutdown();
+
   /* Free NDIS buffer descriptors */
   if (GlobalBufferPool)
     NdisFreeBufferPool(GlobalBufferPool);
@@ -681,11 +668,32 @@ VOID TiUnload(
     IoDeleteDevice(IPDeviceObject);
 
   if (EntityList)
-    ExFreePool(EntityList);
+    PoolFreeBuffer(EntityList);
 
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
 
+VOID STDCALL 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, CriticalWorkQueue );
+       IpWorkItemQueued = TRUE;
+    }
+}
 
 NTSTATUS
 #ifndef _MSC_VER
@@ -704,20 +712,28 @@ DriverEntry(
  */
 {
   NTSTATUS Status;
-  UNICODE_STRING strDeviceName;
-  UNICODE_STRING strNdisDeviceName;
+  UNICODE_STRING strIpDeviceName = RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME);
+  UNICODE_STRING strRawDeviceName = RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME);
+  UNICODE_STRING strUdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
+  UNICODE_STRING strTcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
+  UNICODE_STRING strNdisDeviceName = RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME);
   NDIS_STATUS NdisStatus;
-  NDIS_STRING DeviceName;
+  LARGE_INTEGER DueTime;
 
   TI_DbgPrint(MAX_TRACE, ("Called.\n"));
 
+  TrackingInit();
+  TrackTag(NDIS_BUFFER_TAG);
+  TrackTag(NDIS_PACKET_TAG);
+  TrackTag(FBSD_MALLOC);
+  TrackTag(EXALLOC_TAG);
+
   /* TdiInitialize() ? */
 
   /* FIXME: Create symbolic links in Win32 namespace */
 
   /* Create IP device object */
-  RtlRosInitUnicodeStringFromLiteral(&strDeviceName, DD_IP_DEVICE_NAME);
-  Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
+  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));
@@ -725,8 +741,7 @@ DriverEntry(
   }
 
   /* Create RawIP device object */
-  RtlRosInitUnicodeStringFromLiteral(&strDeviceName, DD_RAWIP_DEVICE_NAME);
-  Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
+  Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName,
     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));
@@ -735,8 +750,7 @@ DriverEntry(
   }
 
   /* Create UDP device object */
-  RtlRosInitUnicodeStringFromLiteral(&strDeviceName, DD_UDP_DEVICE_NAME);
-  Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
+  Status = IoCreateDevice(DriverObject, 0, &strUdpDeviceName,
     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));
@@ -745,8 +759,7 @@ DriverEntry(
   }
 
   /* Create TCP device object */
-  RtlRosInitUnicodeStringFromLiteral(&strDeviceName, DD_TCP_DEVICE_NAME);
-  Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
+  Status = IoCreateDevice(DriverObject, 0, &strTcpDeviceName,
     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));
@@ -754,6 +767,28 @@ DriverEntry(
     return Status;
   }
 
+  /* Setup network layer and transport layer entities */
+  KeInitializeSpinLock(&EntityListLock);
+  EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * MAX_TDI_ENTITIES );
+  if (!NT_SUCCESS(Status)) {
+         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+    TiUnload(DriverObject);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  EntityList[0].tei_entity   = CL_NL_ENTITY;
+  EntityList[0].tei_instance = 0;
+  EntityList[0].context      = 0;
+  EntityList[0].info_req     = InfoNetworkLayerTdiQueryEx;
+  EntityList[0].info_set     = InfoNetworkLayerTdiSetEx;
+  EntityList[1].tei_entity   = CL_TL_ENTITY;
+  EntityList[1].tei_instance = 0;
+  EntityList[1].context      = 0;
+  EntityList[1].info_req     = InfoTransportLayerTdiQueryEx;
+  EntityList[1].info_set     = InfoTransportLayerTdiSetEx;
+  EntityCount = 2;
+  EntityMax   = MAX_TDI_ENTITIES;
+
   /* Allocate NDIS packet descriptors */
   NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT));
   if (NdisStatus != NDIS_STATUS_SUCCESS) {
@@ -780,18 +815,24 @@ DriverEntry(
   InitializeListHead(&InterfaceListHead);
   KeInitializeSpinLock(&InterfaceListLock);
 
+  /* Initialize cancellation queue */
+  InitializeListHead(&CancelQueue);
+  KeInitializeSpinLock(&CancelQueueLock);
+  ExInitializeWorkItem( &CancelQueueWork, CancelQueuePassiveHandler, NULL );
+
   /* Initialize network level protocol subsystem */
-  IPStartup(DriverObject, RegistryPath);
+  IPStartup(RegistryPath);
 
   /* Initialize transport level protocol subsystems */
-  DGStartup();
   RawIPStartup();
   UDPStartup();
   TCPStartup();
 
+  /* Initialize the lan worker */
+  LANStartup();
+
   /* Register protocol with NDIS */
   /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
-  RtlInitUnicodeString(&strNdisDeviceName, TCPIP_PROTOCOL_NAME);       
   Status = LANRegisterProtocol(&strNdisDeviceName);
   if (!NT_SUCCESS(Status)) {
          TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
@@ -814,20 +855,6 @@ DriverEntry(
     return STATUS_INSUFFICIENT_RESOURCES;
   }
 
-  /* Setup network layer and transport layer entities */
-  EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * 2);
-  if (!NT_SUCCESS(Status)) {
-         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-    TiUnload(DriverObject);
-    return STATUS_INSUFFICIENT_RESOURCES;
-  }
-
-  EntityList[0].tei_entity   = CL_NL_ENTITY;
-  EntityList[0].tei_instance = 0;
-  EntityList[1].tei_entity   = CL_TL_ENTITY;
-  EntityList[1].tei_instance = 0;
-  EntityCount = 2;
-
   /* Use direct I/O */
   IPDeviceObject->Flags    |= DO_DIRECT_IO;
   RawIPDeviceObject->Flags |= DO_DIRECT_IO;
@@ -835,13 +862,24 @@ DriverEntry(
   TCPDeviceObject->Flags   |= DO_DIRECT_IO;
 
   /* Initialize the driver object with this driver's entry points */
-  DriverObject->MajorFunction[IRP_MJ_CREATE]  = (PDRIVER_DISPATCH)TiDispatchOpenClose;
-  DriverObject->MajorFunction[IRP_MJ_CLOSE]   = (PDRIVER_DISPATCH)TiDispatchOpenClose;
-  DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)TiDispatchOpenClose;
-  DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)TiDispatchInternal;
-  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)TiDispatch;
-
-  DriverObject->DriverUnload = (PDRIVER_UNLOAD)TiUnload;
+  DriverObject->MajorFunction[IRP_MJ_CREATE]  = TiDispatchOpenClose;
+  DriverObject->MajorFunction[IRP_MJ_CLOSE]   = TiDispatchOpenClose;
+  DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TiDispatchOpenClose;
+  DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal;
+  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch;
+
+  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);
 
   return STATUS_SUCCESS;
 }