This is change 1 of 2.
AddIPAddress and DeleteIPAddress are now implemented all the way down.
Next we need the dhcp service live enough to assign the address from userland,
then we can remove the IP address setting from the kernel.
Modified: trunk/reactos/drivers/lib/ip/network/ip.c
Modified: trunk/reactos/drivers/net/tcpip/include/dispatch.h
Modified: trunk/reactos/drivers/net/tcpip/include/ip.h
Modified: trunk/reactos/drivers/net/tcpip/include/ticonsts.h
Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c
Modified: trunk/reactos/drivers/net/tcpip/tcpip/iinfo.c
Modified: trunk/reactos/drivers/net/tcpip/tcpip/main.c
Modified: trunk/reactos/include/tcpioctl.h
Modified: trunk/reactos/lib/iphlpapi/ifenum_reactos.c
Modified: trunk/reactos/lib/iphlpapi/iphlpapi_main.c
Modified: trunk/reactos/lib/iphlpapi/iphlpapi_private.h

Modified: trunk/reactos/drivers/lib/ip/network/ip.c
--- trunk/reactos/drivers/lib/ip/network/ip.c	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/drivers/lib/ip/network/ip.c	2005-03-24 10:46:52 UTC (rev 14298)
@@ -244,13 +244,29 @@
  */
 {
     KIRQL OldIrql;
+    UINT ChosenIndex = 1;
+    BOOLEAN IndexHasBeenChosen;
     IP_ADDRESS NetworkAddress;
     PNEIGHBOR_CACHE_ENTRY NCE;
+    IF_LIST_ITER(Interface);
 
     TI_DbgPrint(MID_TRACE, ("Called. IF (0x%X).\n", IF));
 
     TcpipAcquireSpinLock(&IF->Lock, &OldIrql);
 
+    /* Choose an index */
+    do {
+        IndexHasBeenChosen = TRUE;
+        ForEachInterface(Interface) {
+            if( Interface->Index == ChosenIndex ) {
+                ChosenIndex++;
+                IndexHasBeenChosen = FALSE;
+            }
+        } EndFor(Interface);
+    } while( !IndexHasBeenChosen );
+
+    IF->Index = ChosenIndex;
+
     /* Add a permanent neighbor for this NTE */
     NCE = NBAddNeighbor(IF, &IF->Unicast, 
 			IF->Address, IF->AddressLength, 

Modified: trunk/reactos/drivers/net/tcpip/include/dispatch.h
--- trunk/reactos/drivers/net/tcpip/include/dispatch.h	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/drivers/net/tcpip/include/dispatch.h	2005-03-24 10:46:52 UTC (rev 14298)
@@ -56,6 +56,14 @@
     PIRP Irp,
     PIO_STACK_LOCATION IrpSp);
 
+NTSTATUS DispTdiSetIPAddress(
+    PIRP Irp,
+    PIO_STACK_LOCATION IrpSp);
+
+NTSTATUS DispTdiDeleteIPAddress(
+    PIRP Irp,
+    PIO_STACK_LOCATION IrpSp);
+
 #endif /* __DISPATCH_H */
 
 /* EOF */

Modified: trunk/reactos/drivers/net/tcpip/include/ip.h
--- trunk/reactos/drivers/net/tcpip/include/ip.h	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/drivers/net/tcpip/include/ip.h	2005-03-24 10:46:52 UTC (rev 14298)
@@ -153,10 +153,16 @@
     UNICODE_STRING Name;          /* Adapter name */
     PUCHAR Address;               /* Pointer to interface address */
     UINT  AddressLength;          /* Length of address in bytes */
+    UINT  Index;                  /* Index of adapter (used to add ip addr) */
     LL_TRANSMIT_ROUTINE Transmit; /* Pointer to transmit function */
     PVOID TCPContext;             /* TCP Content for this interface */
 } IP_INTERFACE, *PIP_INTERFACE;
 
+typedef struct _IP_SET_ADDRESS {
+    ULONG NteIndex;
+    IPv4_RAW_ADDRESS Address;
+    IPv4_RAW_ADDRESS Netmask;
+} IP_SET_ADDRESS, *PIP_SET_ADDRESS;
 
 #define IP_PROTOCOL_TABLE_SIZE 0x100
 

Modified: trunk/reactos/drivers/net/tcpip/include/ticonsts.h
--- trunk/reactos/drivers/net/tcpip/include/ticonsts.h	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/drivers/net/tcpip/include/ticonsts.h	2005-03-24 10:46:52 UTC (rev 14298)
@@ -45,6 +45,12 @@
 #define IOCTL_TCP_SET_INFORMATION_EX \
     _TCP_CTL_CODE(1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
 
+#define IOCTL_SET_IP_ADDRESS \
+    _TCP_CTL_CODE(14, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
+#define IOCTL_DELETE_IP_ADDRESS \
+    _TCP_CTL_CODE(16, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
 /* Unique error values for log entries */
 #define TI_ERROR_DRIVERENTRY 0
 

Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c
--- trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-03-24 10:46:52 UTC (rev 14298)
@@ -1465,4 +1465,56 @@
     return Status;
 }
 
+/* TODO: Support multiple addresses per interface.
+ * For now just set the nte context to the interface index.
+ *
+ * Later on, create an NTE context and NTE instance
+ */
+
+NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
+    NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
+    PIP_SET_ADDRESS IpAddrChange = 
+        (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
+    IF_LIST_ITER(IF);
+
+    ForEachInterface(IF) {
+        if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
+            Status = STATUS_DUPLICATE_OBJECTID;
+            break;
+        }
+        if( IF->Index == IpAddrChange->NteIndex ) {
+            IF->Unicast.Type = IP_ADDRESS_V4;
+            IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
+            IF->Netmask.Type = IP_ADDRESS_V4;
+            IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
+            IpAddrChange->Address = IF->Index;
+            Status = STATUS_SUCCESS;
+            Irp->IoStatus.Information = IF->Index;
+            break;
+        }
+    } EndFor(IF);
+
+    Irp->IoStatus.Status = Status;
+    return Status;
+}
+
+NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
+    IF_LIST_ITER(IF);
+
+    ForEachInterface(IF) {
+        if( IF->Index == *NteIndex ) {
+            IF->Unicast.Type = IP_ADDRESS_V4;
+            IF->Unicast.Address.IPv4Address = 0;
+            IF->Netmask.Type = IP_ADDRESS_V4;
+            IF->Netmask.Address.IPv4Address = 0;
+            Status = STATUS_SUCCESS;
+        }
+    } EndFor(IF);
+
+    Irp->IoStatus.Status = Status;
+    return Status;
+}
+
 /* EOF */

Modified: trunk/reactos/drivers/net/tcpip/tcpip/iinfo.c
--- trunk/reactos/drivers/net/tcpip/tcpip/iinfo.c	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/drivers/net/tcpip/tcpip/iinfo.c	2005-03-24 10:46:52 UTC (rev 14298)
@@ -33,7 +33,7 @@
 
     RtlZeroMemory( OutData, sizeof(IFENTRY) + MAX_IFDESCR_LEN );
 
-    OutData->Index = ID->tei_instance + 1; 
+    OutData->Index = Interface->Index;
     /* viz: tcpip keeps those indices */
     OutData->Type = Interface == 
         Loopback ? MIB_IF_TYPE_LOOPBACK : MIB_IF_TYPE_ETHERNET;
@@ -104,5 +104,7 @@
 				  TDIEntityID *id,
 				  PCHAR Buffer,
 				  UINT BufferSize ) {
+    TI_DbgPrint("Got Request: Class %x Type %x Id %x, EntityID %x:%x\n",
+                InfoClass, InfoId, id->tei_entity, id->tei_instance);
     return TDI_INVALID_REQUEST;
 }

Modified: trunk/reactos/drivers/net/tcpip/tcpip/main.c
--- trunk/reactos/drivers/net/tcpip/tcpip/main.c	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/drivers/net/tcpip/tcpip/main.c	2005-03-24 10:46:52 UTC (rev 14298)
@@ -9,7 +9,7 @@
  */
 #include "precomp.h"
 
-#define NDEBUG
+//#define NDEBUG
 
 #ifndef NDEBUG
 DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER);
@@ -578,6 +578,16 @@
       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));

Modified: trunk/reactos/include/tcpioctl.h
--- trunk/reactos/include/tcpioctl.h	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/include/tcpioctl.h	2005-03-24 10:46:52 UTC (rev 14298)
@@ -37,4 +37,10 @@
 #define IOCTL_TCP_SET_INFORMATION_EX \
     _TCP_CTL_CODE(1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
 
+#define IOCTL_SET_IP_ADDRESS \
+    _TCP_CTL_CODE(14, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
+#define IOCTL_DELETE_IP_ADDRESS \
+    _TCP_CTL_CODE(16, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
 #endif/*_TCPIOCTL_H*/

Modified: trunk/reactos/lib/iphlpapi/ifenum_reactos.c
--- trunk/reactos/lib/iphlpapi/ifenum_reactos.c	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/lib/iphlpapi/ifenum_reactos.c	2005-03-24 10:46:52 UTC (rev 14298)
@@ -754,6 +754,8 @@
                     sizeof(info.if_info) );
         }
         
+        DPRINT1("entry->bDescr = %s\n", entry->bDescr);
+
         closeTcpFile( tcpFile );
     }
 
@@ -795,3 +797,72 @@
   }
   return string;
 }
+
+NTSTATUS addIPAddress( IPAddr Address, IPMask Mask, DWORD IfIndex, 
+                       PULONG NteContext, PULONG NteInstance ) 
+{
+  HANDLE tcpFile;
+  NTSTATUS status = openTcpFile( &tcpFile );
+  IP_SET_DATA Data;
+  IO_STATUS_BLOCK Iosb;
+
+  DPRINT("Called.\n");
+  
+  if( !NT_SUCCESS(status) ) return status;
+
+  Data.NteContext = IfIndex;
+  Data.NewAddress = Address;
+  Data.NewNetmask = Mask;
+
+  status = NtDeviceIoControlFile( tcpFile, 
+                                  NULL,
+                                  NULL,
+                                  NULL, 
+                                  &Iosb,
+                                  IOCTL_SET_IP_ADDRESS,
+                                  &Data,
+                                  sizeof(Data),
+                                  &Data,
+                                  sizeof(Data) );
+
+  closeTcpFile( tcpFile );
+  
+  if( NT_SUCCESS(status) ) {
+      *NteContext = Iosb.Information;
+      *NteInstance = Data.NewAddress;
+  }
+
+  switch( status ) {
+  case STATUS_SUCCESS: return ERROR_SUCCESS;
+  case STATUS_DEVICE_DOES_NOT_EXIST: return ERROR_DEV_NOT_EXIST;
+  default: return status;
+  }
+}
+
+NTSTATUS deleteIpAddress( ULONG NteContext ) 
+{
+  HANDLE tcpFile;
+  NTSTATUS status = openTcpFile( &tcpFile );
+  USHORT TheNteContext = NteContext;
+  IO_STATUS_BLOCK Iosb;
+
+  DPRINT("Called.\n");
+  
+  if( !NT_SUCCESS(status) ) return status;
+
+  status = NtDeviceIoControlFile( tcpFile, 
+                                  NULL,
+                                  NULL,
+                                  NULL, 
+                                  &Iosb,
+                                  IOCTL_DELETE_IP_ADDRESS,
+                                  &NteContext,
+                                  sizeof(USHORT),
+                                  NULL,
+                                  0 );
+
+  closeTcpFile( tcpFile );
+
+  if( NT_SUCCESS(status) ) return ERROR_SUCCESS;
+  else return ERROR_GEN_FAILURE;
+}

Modified: trunk/reactos/lib/iphlpapi/iphlpapi_main.c
--- trunk/reactos/lib/iphlpapi/iphlpapi_main.c	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/lib/iphlpapi/iphlpapi_main.c	2005-03-24 10:46:52 UTC (rev 14298)
@@ -82,11 +82,9 @@
  *  DWORD
  *
  */
-DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance)
+DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance)
 {
-  FIXME(":stub\n");
-  /* marking Win2K+ functions not supported */
-  return ERROR_NOT_SUPPORTED;
+    return addIPAddress( Address, Netmask, IfIndex, NteContext, NteInstance );
 }
 
 
@@ -404,9 +402,7 @@
 DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
 {
   TRACE("NTEContext %ld\n", NTEContext);
-  FIXME(":stub\n");
-  /* marking Win2K+ functions not supported */
-  return ERROR_NOT_SUPPORTED;
+  return deleteIpAddress( NTEContext );
 }
 
 

Modified: trunk/reactos/lib/iphlpapi/iphlpapi_private.h
--- trunk/reactos/lib/iphlpapi/iphlpapi_private.h	2005-03-24 07:50:41 UTC (rev 14297)
+++ trunk/reactos/lib/iphlpapi/iphlpapi_private.h	2005-03-24 10:46:52 UTC (rev 14298)
@@ -82,6 +82,12 @@
     IPAddrEntry        ip_addr;
 } IFInfo;
 
+typedef struct _IP_SET_DATA {
+    ULONG NteContext;
+    ULONG NewAddress;
+    ULONG NewNetmask;
+} IP_SET_DATA, *PIP_SET_DATA;
+
 typedef enum _IPHLPAddrType {
     IPAAddr, IPABcast, IPAMask, IFMtu, IFStatus
 } IPHLPAddrType;