Fix getInterfaceInfoSet so GetInterfaceInfo returns only non-loopback adapters, howev...
[reactos.git] / reactos / lib / iphlpapi / ifenum_reactos.c
index 7486b94..91dd58a 100644 (file)
  * - We don't support IPv6 addresses here yet -- I moved the upper edge
  *   functions into iphlpv6.c (arty)
  */
-
 #include "iphlpapi_private.h"
 #include "ifenum.h"
+#include <assert.h>
+
+#define NDEBUG
+#include "debug.h"
 
 /* Globals */
 const PWCHAR TcpFileName = L"\\Device\\Tcp";
@@ -77,7 +80,8 @@ NTSTATUS openTcpFile(PHANDLE tcpFile) {
                                 NULL );
 
     status = ZwCreateFile( tcpFile,
-                           SYNCHRONIZE | GENERIC_EXECUTE,
+                           SYNCHRONIZE | GENERIC_EXECUTE | 
+                           GENERIC_READ | GENERIC_WRITE,
                            &objectAttributes,
                            &ioStatusBlock,
                            NULL,
@@ -128,15 +132,15 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
     DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES, 
         arraySize = entrySize * MAX_TDI_ENTITIES;
 
-    DbgPrint("TdiGetSetOfThings(tcpFile %x,toiClass %x,toiType %x,toiId %x,"
-           "teiEntity %x,fixedPart %d,entrySize %d)\n",
-           (int)tcpFile, 
-           (int)toiClass, 
-           (int)toiType, 
-           (int)toiId, 
-           (int)teiEntity,
-           (int)fixedPart, 
-           (int)entrySize );
+    TRACE("TdiGetSetOfThings(tcpFile %x,toiClass %x,toiType %x,toiId %x,"
+          "teiEntity %x,fixedPart %d,entrySize %d)\n",
+          (int)tcpFile, 
+          (int)toiClass, 
+          (int)toiType, 
+          (int)toiId, 
+          (int)teiEntity,
+          (int)fixedPart, 
+          (int)entrySize );
 
     req.ID.toi_class                = toiClass;
     req.ID.toi_type                 = toiType;
@@ -152,7 +156,7 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
      * stabilizes.
      */
     do {
-        ASSERT( !entitySet ); /* We must not have an entity set allocated */
+        assert( !entitySet ); /* We must not have an entity set allocated */
         status = DeviceIoControl( tcpFile,
                                   IOCTL_TCP_QUERY_INFORMATION_EX,
                                   &req,
@@ -162,8 +166,10 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
                                   &allocationSizeForEntityArray,
                                   NULL );
 
-        if( !NT_SUCCESS(status) ) {
-            return status;
+        if(!status)
+        {
+            DPRINT("IOCTL Failed\n");
+            return STATUS_UNSUCCESSFUL;
         }
         
         arraySize = allocationSizeForEntityArray;
@@ -191,9 +197,10 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
         HeapFree( GetProcessHeap(), 0, entitySet );
         entitySet = 0;
 
-        if( !NT_SUCCESS(status) ) {
-            DPRINT("TdiGetSetOfThings() => %08x\n", (int)status);
-            return status;
+        if(!status)
+        {
+            DPRINT("IOCTL Failed\n");
+            return STATUS_UNSUCCESSFUL;
         }
 
         DPRINT("TdiGetSetOfThings(): Array changed size: %d -> %d.\n",
@@ -237,10 +244,11 @@ NTSTATUS tdiGetMibForIfEntity
                               &returnSize,
                               NULL );
 
-    if( !NT_SUCCESS(status) ) {
-        TRACE("failure: %08x\n", status);
-        return status;
-    } else TRACE("Success.\n");
+    if(!status)
+    {
+            DPRINT("IOCTL Failed\n");
+            return STATUS_UNSUCCESSFUL;
+    }
 
     DPRINT("TdiGetMibForIfEntity() => {\n"
            "  if_index ....................... %x\n"
@@ -300,13 +308,14 @@ static BOOL isInterface( TDIEntityID *if_maybe ) {
 
 static BOOL isLoopback( HANDLE tcpFile, TDIEntityID *loop_maybe ) {
     IFEntrySafelySized entryInfo;
+    NTSTATUS status;
 
-    tdiGetMibForIfEntity( tcpFile, 
-                          loop_maybe,
-                          &entryInfo );
+    status = tdiGetMibForIfEntity( tcpFile, 
+                                   loop_maybe,
+                                   &entryInfo );
 
-    return !entryInfo.ent.if_type || 
-        entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK;
+    return NT_SUCCESS(status) && (!entryInfo.ent.if_type || 
+        entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK);
 }
 
 NTSTATUS tdiGetEntityType( HANDLE tcpFile, TDIEntityID *ent, PULONG type ) {
@@ -334,7 +343,7 @@ NTSTATUS tdiGetEntityType( HANDLE tcpFile, TDIEntityID *ent, PULONG type ) {
 
     DPRINT("TdiGetEntityType() => %08x %08x\n", *type, status);
 
-    return status;
+    return (status ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
 }
 
 static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile, 
@@ -354,6 +363,7 @@ static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
     if( infoSetInt ) {
         for( i = 0; i < numEntities; i++ ) {
             if( isInterface( &entIDSet[i] ) ) {
+                infoSetInt[curInterf].entity_id = entIDSet[i];
                 status = tdiGetMibForIfEntity
                     ( tcpFile,
                       &entIDSet[i],
@@ -363,20 +373,20 @@ static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
                     DWORD numAddrs;
                     IPAddrEntry *addrs;
                     TDIEntityID ip_ent;
-                    int j,k;
+                    int j;
 
                     interfaceInfoComplete = FALSE;
                    status = getNthIpEntity( tcpFile, 0, &ip_ent );
                    if( NT_SUCCESS(status) )
                        status = tdiGetIpAddrsForIpEntity
                            ( tcpFile, &ip_ent, &addrs, &numAddrs );
-                   for( k = 0; k < numAddrs && NT_SUCCESS(status); k++ ) {
-                       DPRINT("ADDR %d: index %d (target %d)\n", k, addrs[k].iae_index, infoSetInt[curInterf].if_info.ent.if_index);
-                       if( addrs[k].iae_index == 
+                   for( j = 0; j < numAddrs && NT_SUCCESS(status); j++ ) {
+                       DPRINT("ADDR %d: index %d (target %d)\n", j, addrs[j].iae_index, infoSetInt[curInterf].if_info.ent.if_index);
+                       if( addrs[j].iae_index == 
                            infoSetInt[curInterf].if_info.ent.if_index ) {
                            memcpy( &infoSetInt[curInterf].ip_addr,
-                                   &addrs[k],
-                                   sizeof( addrs[k] ) );
+                                   &addrs[j],
+                                   sizeof( addrs[j] ) );
                            curInterf++;
                            break;
                        }
@@ -384,12 +394,18 @@ static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
                 }
             }
         }
-    }
 
-    *infoSet = infoSetInt;
-    *numInterfaces = curInterf;
+        if (NT_SUCCESS(status)) {
+            *infoSet = infoSetInt;
+            *numInterfaces = curInterf;
+        } else {
+            HeapFree(GetProcessHeap(), 0, infoSetInt);
+        }
 
-    return STATUS_SUCCESS;
+        return status;
+    } else {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
 }
 
 static DWORD getNumInterfacesInt(BOOL onlyNonLoopback)
@@ -414,8 +430,6 @@ static DWORD getNumInterfacesInt(BOOL onlyNonLoopback)
         return 0;
     }
 
-    closeTcpFile( tcpFile );
-
     for( i = 0; i < numEntities; i++ ) {
         if( isInterface( &entitySet[i] ) &&
             (!onlyNonLoopback || 
@@ -426,6 +440,8 @@ static DWORD getNumInterfacesInt(BOOL onlyNonLoopback)
     DPRINT("getNumInterfaces: success: %d %d %08x\n", 
            onlyNonLoopback, numInterfaces, status );
 
+    closeTcpFile( tcpFile );
+
     tdiFreeThingSet( entitySet );
     
     return numInterfaces;
@@ -754,6 +770,8 @@ DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
                     sizeof(info.if_info) );
         }
         
+        DPRINT("entry->bDescr = %s\n", entry->bDescr);
+
         closeTcpFile( tcpFile );
     }
 
@@ -795,3 +813,71 @@ char *toIPAddressString(unsigned int addr, char string[16])
   }
   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 );
+  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;
+}