Revert my patch from yesterday. Need to take more time to work on it.
[reactos.git] / reactos / drivers / net / tcpip / tcpip / main.c
index ab6c7e5..b6e7c32 100644 (file)
@@ -9,10 +9,10 @@
  */
 #include "precomp.h"
 
-//#define NDEBUG
+#define NDEBUG
 
 #ifndef NDEBUG
-DWORD DebugTraceLevel = 0x7fffffff;
+DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER);
 #else
 DWORD DebugTraceLevel = 0;
 #endif /* NDEBUG */
@@ -29,6 +29,11 @@ ULONG EntityCount                = 0;
 ULONG EntityMax                  = 0;
 UDP_STATISTICS UDPStats;
 
+/* Network timers */
+KTIMER IPTimer;
+KDPC IPTimeoutDpc;
+KSPIN_LOCK IpWorkLock;
+WORK_QUEUE_ITEM IpWorkItem;
 
 VOID TiWriteErrorLog(
     PDRIVER_OBJECT DriverContext,
@@ -45,7 +50,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
  */
@@ -57,7 +63,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) {
@@ -96,46 +102,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:
@@ -144,6 +110,7 @@ NTSTATUS TiGetProtocolNumber(
  * RETURNS:
  *     Status of the operation
  */
+
 NTSTATUS TiCreateFileObject(
   PDEVICE_OBJECT DeviceObject,
   PIRP Irp)
@@ -178,7 +145,6 @@ CP
     return STATUS_INSUFFICIENT_RESOURCES;
   }
 CP
-  Context->RefCount   = 1;
   Context->CancelIrps = FALSE;
   KeInitializeEvent(&Context->CleanupEvent, NotificationEvent, FALSE);
 CP
@@ -187,8 +153,8 @@ CP
   Request.RequestContext       = Irp;
 CP
   /* Branch to the right handler */
-  if (EaInfo && 
-      (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) && 
+  if (EaInfo &&
+      (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
       (RtlCompareMemory
        (&EaInfo->EaName, TdiTransportAddress,
        TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
@@ -207,18 +173,17 @@ CP
       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", 
+         TI_DbgPrint(MIN_TRACE, ("AddressLength: %\n",
                                  Address->Address[0].AddressLength));
-         TI_DbgPrint(MIN_TRACE, ("AddressType: %\n", 
+         TI_DbgPrint(MIN_TRACE, ("AddressType: %\n",
                                  Address->Address[0].AddressType));
       }
-      ExFreePool(Context);
+      PoolFreeBuffer(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;
@@ -230,12 +195,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
@@ -245,11 +210,11 @@ CP
       Context->Handle.AddressHandle = Request.Handle.AddressHandle;
     }
 CP
-  } else if (EaInfo && 
-            (EaInfo->EaNameLength == 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) ==
              TDI_CONNECTION_CONTEXT_LENGTH)) {
     /* This is a request to open a connection endpoint */
 CP
@@ -257,7 +222,7 @@ CP
 
     if (EaInfo->EaValueLength < sizeof(PVOID)) {
       TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
-      ExFreePool(Context);
+      PoolFreeBuffer(Context);
       return STATUS_INVALID_PARAMETER;
     }
 
@@ -265,7 +230,7 @@ CP
 
     if (DeviceObject != TCPDeviceObject) {
       TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
-      ExFreePool(Context);
+      PoolFreeBuffer(Context);
       return STATUS_INVALID_PARAMETER;
     }
 
@@ -288,10 +253,11 @@ CP
   }
 
   if (!NT_SUCCESS(Status))
-    ExFreePool(Context);
+    PoolFreeBuffer(Context);
 
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
 
+  Irp->IoStatus.Status = Status;
   return Status;
 }
 
@@ -316,16 +282,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);
 
@@ -354,7 +312,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;
@@ -400,10 +358,10 @@ NTSTATUS TiCleanupFileObject(
 
   if (Status != STATUS_PENDING)
     TiCleanupFileObjectComplete(Irp, Status);
-  
+
   KeWaitForSingleObject(&Context->CleanupEvent,
     UserRequest, KernelMode, FALSE, NULL);
-  
+
   return Irp->IoStatus.Status;
 }
 
@@ -445,11 +403,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);
@@ -503,6 +461,7 @@ TiDispatchInternal(
 
   case TDI_RECEIVE_DATAGRAM:
     Status = DispTdiReceiveDatagram(Irp);
+    Complete = FALSE;
     break;
 
   case TDI_SEND:
@@ -512,6 +471,7 @@ TiDispatchInternal(
 
   case TDI_SEND_DATAGRAM:
     Status = DispTdiSendDatagram(Irp);
+    Complete = FALSE;
     break;
 
   case TDI_ACCEPT:
@@ -520,6 +480,7 @@ TiDispatchInternal(
 
   case TDI_LISTEN:
     Status = DispTdiListen(Irp);
+    Complete = FALSE;
     break;
 
   case TDI_CONNECT:
@@ -562,7 +523,7 @@ TiDispatchInternal(
 
   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
 
-  if( Complete ) 
+  if( Complete )
       IRPFinish( Irp, Status );
 
   return Status;
@@ -608,15 +569,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")); 
+      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")); 
+      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));
@@ -642,12 +613,14 @@ VOID STDCALL 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);
@@ -659,7 +632,6 @@ VOID STDCALL TiUnload(
   TCPShutdown();
   UDPShutdown();
   RawIPShutdown();
-  DGShutdown();
 
   /* Shutdown network level protocol subsystem */
   IPShutdown();
@@ -690,11 +662,32 @@ VOID STDCALL 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
@@ -713,12 +706,16 @@ 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;
+  LARGE_INTEGER DueTime;
 
   TI_DbgPrint(MAX_TRACE, ("Called.\n"));
-  
+
   TrackingInit();
   TrackTag(NDIS_BUFFER_TAG);
   TrackTag(NDIS_PACKET_TAG);
@@ -730,8 +727,7 @@ DriverEntry(
   /* 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));
@@ -739,8 +735,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));
@@ -749,8 +744,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));
@@ -759,8 +753,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));
@@ -816,21 +809,19 @@ DriverEntry(
   InitializeListHead(&InterfaceListHead);
   KeInitializeSpinLock(&InterfaceListLock);
 
-  /* Initialize the lan worker */
-  LANStartup();
-
   /* 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));
@@ -868,7 +859,16 @@ DriverEntry(
 
   DriverObject->DriverUnload = TiUnload;
 
-  PREPARE_TESTS
+  /* 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;
 }