Beispiel #1
0
const char *getInterfaceNameByIndex(DWORD index)
{
    IFInfo ifInfo;
    HANDLE tcpFile;
    char *interfaceName = 0, *adapter_name = 0;
    NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );

    if( NT_SUCCESS(status) ) {
        status = getInterfaceInfoByIndex( tcpFile, index, &ifInfo );

        if( NT_SUCCESS(status) ) {
            adapter_name = (char *)ifInfo.if_info.ent.if_descr;

            interfaceName = HeapAlloc( GetProcessHeap(), 0,
                                       strlen(adapter_name) + 1 );
            if (!interfaceName) return NULL;

            strcpy( interfaceName, adapter_name );
        }

        closeTcpFile( tcpFile );
    }

    return interfaceName;
}
Beispiel #2
0
NTSTATUS deleteIpAddress( ULONG NteContext )
{
  HANDLE tcpFile;
  NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA );
  IO_STATUS_BLOCK Iosb;

  TRACE("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)) {
      ERR("deleteIpAddress(%lu) returning 0x%lx\n", NteContext, status);
  }

  return status;
}
DWORD deleteIpForwardEntry( PMIB_IPFORWARDROW pRoute ) {
    HANDLE tcpFile;
    NTSTATUS status = openTcpFile( &tcpFile );
    TCP_REQUEST_SET_INFORMATION_EX_ROUTE_ENTRY req =
        TCP_REQUEST_SET_INFORMATION_INIT;
    IPRouteEntry *rte;
    TDIEntityID   id;
    DWORD         returnSize = 0;

    TRACE("Called.\n");

    if( NT_SUCCESS(status) ) {
        status = getNthIpEntity( tcpFile, pRoute->dwForwardIfIndex, &id );

        if( NT_SUCCESS(status) ) {
            req.Req.ID.toi_class                = INFO_CLASS_PROTOCOL;
            req.Req.ID.toi_type                 = INFO_TYPE_PROVIDER;
            req.Req.ID.toi_id                   = IP_MIB_ARPTABLE_ENTRY_ID;
            req.Req.ID.toi_entity.tei_instance  = id.tei_instance;
            req.Req.ID.toi_entity.tei_entity    = CL_NL_ENTITY;
            req.Req.BufferSize                  = sizeof(*rte);
            rte                                 =
                (IPRouteEntry *)&req.Req.Buffer[0];

            // dwForwardPolicy
            // dwForwardNextHopAS
            rte->ire_dest    = pRoute->dwForwardDest;
            rte->ire_mask    = INADDR_NONE;
            rte->ire_gw      = pRoute->dwForwardNextHop;
            rte->ire_index   = pRoute->dwForwardIfIndex;
            rte->ire_type    = IP_FORWARD_DEL;
            rte->ire_proto   = pRoute->dwForwardProto;
            rte->ire_age     = pRoute->dwForwardAge;
            rte->ire_metric1 = pRoute->dwForwardMetric1;
            rte->ire_metric2 = INADDR_NONE;
            rte->ire_metric3 = INADDR_NONE;
            rte->ire_metric4 = INADDR_NONE;
            rte->ire_metric5 = INADDR_NONE;

            status = DeviceIoControl( tcpFile,
                                      IOCTL_TCP_SET_INFORMATION_EX,
                                      &req,
                                      sizeof(req),
                                      NULL,
                                      0,
                                      &returnSize,
                                      NULL );
        }

        closeTcpFile( tcpFile );
    }

    TRACE("Returning: %08x (IOCTL was %08x)\n", status, IOCTL_TCP_SET_INFORMATION_EX);

    if( NT_SUCCESS(status) )
	return NO_ERROR;
    else
	return status;
}
Beispiel #4
0
DWORD getNumArpEntries(void)
{
    DWORD numEntities;
    TDIEntityID *entitySet = NULL;
    HANDLE tcpFile;
    int i, totalNumber = 0;
    NTSTATUS status;
    PMIB_IPNETROW IpArpTable = NULL;
    DWORD returnSize;

    TRACE("called.\n");

    status = openTcpFile( &tcpFile );

    if( !NT_SUCCESS(status) ) {
        TRACE("failure: %08x\n", (int)status );
        return 0;
    }

    status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );

    for( i = 0; i < numEntities; i++ ) {
        if( isInterface( &entitySet[i] ) &&
	    hasArp( tcpFile, &entitySet[i] ) ) {

	    status = tdiGetSetOfThings( tcpFile,
					INFO_CLASS_PROTOCOL,
					INFO_TYPE_PROVIDER,
					IP_MIB_ARPTABLE_ENTRY_ID,
					AT_ENTITY,
					entitySet[i].tei_instance,
					0,
					sizeof(MIB_IPNETROW),
					(PVOID *)&IpArpTable,
					&returnSize );

	    if( status == STATUS_SUCCESS ) totalNumber += returnSize;
		if( IpArpTable ) {
			tdiFreeThingSet( IpArpTable );
			IpArpTable = NULL;
		}
	}
    }

    closeTcpFile( tcpFile );
    if( IpArpTable ) tdiFreeThingSet( IpArpTable );
    if( entitySet ) tdiFreeThingSet( entitySet );
    return totalNumber;
}
DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
                                 PDWORD type)
{
    HANDLE tcpFile;
    IFInfo info;
    NTSTATUS status = openTcpFile( &tcpFile );

    if( NT_SUCCESS(status) ) {
        status = getInterfaceInfoByName( tcpFile, (char *)name, &info );
        if( NT_SUCCESS(status) )
            getInterfacePhysicalFromInfo( &info, len, addr, type );
        closeTcpFile( tcpFile );
    }

    return status;
}
Beispiel #6
0
DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
 PDWORD type)
{
    HANDLE tcpFile;
    IFInfo info;
    NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );

    if( NT_SUCCESS(status) ) {
        status = getInterfaceInfoByIndex( tcpFile, index, &info );
        if( NT_SUCCESS(status) )
            getInterfacePhysicalFromInfo( &info, len, addr, type );
        closeTcpFile( tcpFile );
    }

    return status;
}
Beispiel #7
0
InterfaceIndexTable *getInterfaceIndexTableInt( BOOL nonLoopbackOnly ) {
  DWORD numInterfaces, curInterface = 0;
  int i;
  IFInfo *ifInfo;
  InterfaceIndexTable *ret = 0;
  HANDLE tcpFile;
  NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );

  if( NT_SUCCESS(status) ) {
      status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces );

      TRACE("InterfaceInfoSet: %08x, %04x:%08x\n",
	     status,
	     ifInfo->entity_id.tei_entity,
	     ifInfo->entity_id.tei_instance);

      if( NT_SUCCESS(status) ) {
          ret = (InterfaceIndexTable *)
              calloc(1,
                     sizeof(InterfaceIndexTable) +
                     (numInterfaces - 1) * sizeof(DWORD));

          if (ret) {
              ret->numAllocated = numInterfaces;
	      TRACE("NumInterfaces = %d\n", numInterfaces);

              for( i = 0; i < numInterfaces; i++ ) {
		  TRACE("Examining interface %d\n", i);
                  if( !nonLoopbackOnly ||
                      !isLoopback( tcpFile, &ifInfo[i].entity_id ) ) {
		      TRACE("Interface %d matches (%d)\n", i, curInterface);
                      ret->indexes[curInterface++] =
                          ifInfo[i].if_info.ent.if_index;
                  }
              }

              ret->numIndexes = curInterface;
          }

          tdiFreeThingSet( ifInfo );
      }
      closeTcpFile( tcpFile );
  }

  return ret;
}
Beispiel #8
0
DWORD getNumRoutes(void)
{
    DWORD numEntities, numRoutes = 0;
    TDIEntityID *entitySet;
    HANDLE tcpFile;
    int i;
    NTSTATUS status;

    TRACE("called.\n");

    status = openTcpFile( &tcpFile );

    if( !NT_SUCCESS(status) ) {
        TRACE("failure: %08x\n", (int)status );
        return 0;
    }

    status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );

    if( !NT_SUCCESS(status) ) {
        TRACE("failure: %08x\n", (int)status );
        closeTcpFile( tcpFile );
        return 0;
    }

    for( i = 0; i < numEntities; i++ ) {
        if( isIpEntity( tcpFile, &entitySet[i] ) ) {
            IPSNMPInfo isnmp;
            memset( &isnmp, 0, sizeof( isnmp ) );
            status = tdiGetMibForIpEntity( tcpFile, &entitySet[i], &isnmp );
            if( !NT_SUCCESS(status) ) {
                tdiFreeThingSet( entitySet );
                closeTcpFile( tcpFile );
                return status;
            }
            numRoutes += isnmp.ipsi_numroutes;
        }
    }

    TRACE("numRoutes: %d\n", (int)numRoutes);

    closeTcpFile( tcpFile );

    return numRoutes;
}
Beispiel #9
0
DWORD getInterfaceIndexByName(const char *name, PDWORD index)
{
    IFInfo ifInfo;
    HANDLE tcpFile;
    NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );

    if( NT_SUCCESS(status) ) {
        status = getInterfaceInfoByName( tcpFile, (char *)name, &ifInfo );

        if( NT_SUCCESS(status) ) {
            *index = ifInfo.if_info.ent.if_index;
        }

        closeTcpFile( tcpFile );
    }

    return status;
}
Beispiel #10
0
NTSTATUS addIPAddress( IPAddr Address, IPMask Mask, DWORD IfIndex,
                       PULONG NteContext, PULONG NteInstance )
{
  HANDLE tcpFile;
  NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA );
  IP_SET_DATA Data;
  IO_STATUS_BLOCK Iosb;

  TRACE("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;
  }

  if (!NT_SUCCESS(status)) {
      ERR("addIPAddress for if %d returning 0x%lx\n", IfIndex, status);
  }

  return status;

}
Beispiel #11
0
static DWORD getNumInterfacesInt(BOOL onlyNonLoopback)
{
    DWORD numEntities, numInterfaces = 0;
    TDIEntityID *entitySet;
    HANDLE tcpFile;
    NTSTATUS status;
    int i;

    status = openTcpFile( &tcpFile, FILE_READ_DATA );

    if( !NT_SUCCESS(status) ) {
        WARN("getNumInterfaces: failed %08x\n", status );
        return 0;
    }

    status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );

    if( !NT_SUCCESS(status) ) {
        WARN("getNumInterfaces: failed %08x\n", status );
        closeTcpFile( tcpFile );
        return 0;
    }

    for( i = 0; i < numEntities; i++ ) {
        if( isInterface( &entitySet[i] ) &&
            (!onlyNonLoopback ||
	     (onlyNonLoopback && !isLoopback( tcpFile, &entitySet[i] ))) )
            numInterfaces++;
    }

    TRACE("getNumInterfaces: success: %d %d %08x\n",
           onlyNonLoopback, numInterfaces, status );

    closeTcpFile( tcpFile );

    tdiFreeThingSet( entitySet );

    return numInterfaces;
}
Beispiel #12
0
DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry)
{
    HANDLE tcpFile;
    IFInfo info;
    NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );

    TRACE("Called.\n");

    if( NT_SUCCESS(status) ) {
        status = getInterfaceInfoByIndex( tcpFile, index, &info );

        if( NT_SUCCESS(status) ) {
            memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN],
                    &info.if_info,
                    sizeof(info.if_info) );
        }

        closeTcpFile( tcpFile );
    }

    return status;
}
Beispiel #13
0
DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
{
    HANDLE tcpFile;
    IFInfo info;
    NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );

    TRACE("Called.\n");

    if( NT_SUCCESS(status) ) {
        status = getInterfaceInfoByName( tcpFile, (char *)name, &info );

        if( NT_SUCCESS(status) ) {
            memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN],
                    &info.if_info,
                    sizeof(info.if_info) );
        }

        TRACE("entry->bDescr = %s\n", entry->bDescr);

        closeTcpFile( tcpFile );
    }

    return status;
}
Beispiel #14
0
DWORD getAddrByIndexOrName( char *name, DWORD index, IPHLPAddrType addrType ) {
    IFInfo ifInfo;
    HANDLE tcpFile;
    NTSTATUS status = STATUS_SUCCESS;
    DWORD addrOut = INADDR_ANY;

    status = openTcpFile( &tcpFile, FILE_READ_DATA );

    if( NT_SUCCESS(status) ) {
        status = getIPAddrEntryForIf( tcpFile, name, index, &ifInfo );
        if( NT_SUCCESS(status) ) {
            switch( addrType ) {
            case IPAAddr:  addrOut = ifInfo.ip_addr.iae_addr; break;
            case IPABcast: addrOut = ifInfo.ip_addr.iae_bcastaddr; break;
            case IPAMask:  addrOut = ifInfo.ip_addr.iae_mask; break;
            case IFMtu:    addrOut = ifInfo.if_info.ent.if_mtu; break;
            case IFStatus: addrOut = ifInfo.if_info.ent.if_operstatus; break;
            }
        }
        closeTcpFile( tcpFile );
    }

    return addrOut;
}
Beispiel #15
0
PMIB_IPNETTABLE getArpTable(void)
{
    DWORD numEntities, returnSize;
    TDIEntityID *entitySet;
    HANDLE tcpFile;
    int i, totalNumber, TmpIdx, CurrIdx = 0;
    NTSTATUS status;
    PMIB_IPNETTABLE IpArpTable = NULL;
    PMIB_IPNETROW AdapterArpTable = NULL;

    TRACE("called.\n");

    totalNumber = getNumArpEntries();

    status = openTcpFile( &tcpFile );

    if( !NT_SUCCESS(status) ) {
        TRACE("failure: %08x\n", (int)status );
        return 0;
    }

    IpArpTable = HeapAlloc
	( GetProcessHeap(), 0,
	  sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber) );
    if (!IpArpTable) {
        closeTcpFile(tcpFile);
        return NULL;
    }

    status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );

    for( i = 0; i < numEntities; i++ ) {
        if( isInterface( &entitySet[i] ) &&
	    hasArp( tcpFile, &entitySet[i] ) ) {

	    status = tdiGetSetOfThings( tcpFile,
					INFO_CLASS_PROTOCOL,
					INFO_TYPE_PROVIDER,
					IP_MIB_ARPTABLE_ENTRY_ID,
					AT_ENTITY,
					entitySet[i].tei_instance,
					0,
					sizeof(MIB_IPNETROW),
					(PVOID *)&AdapterArpTable,
					&returnSize );

            if( status == STATUS_SUCCESS ) {
                for( TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++ )
                    IpArpTable->table[CurrIdx] = AdapterArpTable[TmpIdx];
                tdiFreeThingSet( AdapterArpTable );
            }
        }
    }

    closeTcpFile( tcpFile );

    tdiFreeThingSet( entitySet );
    IpArpTable->dwNumEntries = CurrIdx;

    return IpArpTable;
}
Beispiel #16
0
RouteTable *getRouteTable(void)
{
    RouteTable *out_route_table;
    DWORD numRoutes = getNumRoutes(), routesAdded = 0;
    TDIEntityID ent;
    HANDLE tcpFile;
    NTSTATUS status = openTcpFile( &tcpFile );
    int i;

    if( !NT_SUCCESS(status) )
        return 0;

    TRACE("GETTING ROUTE TABLE\n");

    out_route_table = HeapAlloc( GetProcessHeap(), 0,
                                 sizeof(RouteTable) +
                                 (sizeof(RouteEntry) * (numRoutes - 1)) );
    if (!out_route_table) {
        closeTcpFile(tcpFile);
        return NULL;
    }

    out_route_table->numRoutes = numRoutes;

    for( i = 0; routesAdded < out_route_table->numRoutes; i++ ) {
        int j;
        IPRouteEntry *route_set;

        getNthIpEntity( tcpFile, i, &ent );

        tdiGetRoutesForIpEntity( tcpFile, &ent, &route_set, &numRoutes );
        
        if( !route_set ) {
            closeTcpFile( tcpFile );
            HeapFree( GetProcessHeap(), 0, out_route_table );
            return 0;
        }

        TRACE( "%d routes in instance %d\n", numRoutes, i );
#if 0
        HexDump( route_set,
                 sizeof( IPRouteEntry ) *
                 snmpInfo.ipsi_numroutes );
#endif

        for( j = 0; j < numRoutes; j++ ) {
            int routeNum = j + routesAdded;
            out_route_table->routes[routeNum].dest =
                route_set[j].ire_dest;
            out_route_table->routes[routeNum].mask =
                route_set[j].ire_mask;
            out_route_table->routes[routeNum].gateway =
                route_set[j].ire_gw;
            out_route_table->routes[routeNum].ifIndex =
                route_set[j].ire_index;
            out_route_table->routes[routeNum].metric =
                route_set[j].ire_metric1;
        }

        if( route_set ) tdiFreeThingSet( route_set );

        routesAdded += numRoutes;
    }

    closeTcpFile( tcpFile );

    TRACE("Return: %08x, %08x\n", status, out_route_table);

    return out_route_table;
}
Beispiel #17
0
DWORD
WINAPI
DECLSPEC_HOTPATCH
GetAdaptersAddresses(
    _In_ ULONG Family,
    _In_ ULONG Flags,
    _In_ PVOID Reserved,
    _Inout_ PIP_ADAPTER_ADDRESSES pAdapterAddresses,
    _Inout_ PULONG pOutBufLen)
{
    NTSTATUS Status;
    HANDLE TcpFile;
    TDIEntityID* InterfacesList;
    ULONG InterfacesCount;
    ULONG AdaptersCount = 0;
    ULONG i;
    ULONG TotalSize = 0, RemainingSize;
    BYTE* Ptr = (BYTE*)pAdapterAddresses;
    DWORD MIN_SIZE = 15 * 1024;
    PIP_ADAPTER_ADDRESSES PreviousAA = NULL;

    FIXME("GetAdaptersAddresses - Semi Stub: Family %u, Flags 0x%08x, Reserved %p, pAdapterAddress %p, pOutBufLen %p.\n",
        Family, Flags, Reserved, pAdapterAddresses, pOutBufLen);

    if (!pOutBufLen)
        return ERROR_INVALID_PARAMETER;

    // FIXME: the exact needed size should be computed first, BEFORE doing any write to the output buffer.
    // As suggested by MSDN, require a 15 KB buffer, which allows to React properly to length checks.
    if(!Ptr || *pOutBufLen < MIN_SIZE)
    {
        *pOutBufLen = MIN_SIZE;
        return ERROR_BUFFER_OVERFLOW;
    }

    switch(Family)
    {
        case AF_INET:
            break;
        case AF_INET6:
            /* One day maybe... */
            FIXME("IPv6 is not supported in ReactOS!\n");
            /* We got nothing to say in this case */
            return ERROR_NO_DATA;
            break;
        case AF_UNSPEC:
            WARN("IPv6 addresses ignored, IPv4 only\n");
            Family = AF_INET;
            break;
        default:
            ERR("Invalid family 0x%x\n", Family);
            return ERROR_INVALID_PARAMETER;
            break;
    }

    RemainingSize = *pOutBufLen;
    if (Ptr)
        ZeroMemory(Ptr, RemainingSize);

    /* open the tcpip driver */
    Status = openTcpFile(&TcpFile, FILE_READ_DATA);
    if (!NT_SUCCESS(Status))
    {
        ERR("Could not open handle to tcpip.sys. Status %08x\n", Status);
        return RtlNtStatusToDosError(Status);
    }

    /* Get the interfaces list */
    Status = GetInterfacesList(TcpFile, &InterfacesList, &InterfacesCount);
    if (!NT_SUCCESS(Status))
    {
        ERR("Could not get adapters list. Status %08x\n", Status);
        NtClose(TcpFile);
        return RtlNtStatusToDosError(Status);
    }

    /* Let's see if we got any adapter. */
    for (i = 0; i < InterfacesCount; i++)
    {
        PIP_ADAPTER_ADDRESSES CurrentAA = (PIP_ADAPTER_ADDRESSES)Ptr;
        ULONG CurrentAASize = 0;

        if (InterfacesList[i].tei_entity == IF_ENTITY)
        {
            BYTE EntryBuffer[FIELD_OFFSET(IFEntry, if_descr) +
                             RTL_FIELD_SIZE(IFEntry, if_descr[0]) * (MAX_ADAPTER_DESCRIPTION_LENGTH + 1)];
            IFEntry* Entry = (IFEntry*)EntryBuffer;

            /* Remember we got one */
            AdaptersCount++;

            /* Set the pointer to this instance in the previous one*/
            if(PreviousAA)
                PreviousAA->Next = CurrentAA;

            /* Of course we need some space for the base structure. */
            CurrentAASize = sizeof(IP_ADAPTER_ADDRESSES);

            /* Get the entry */
            Status = GetInterfaceEntry(TcpFile, InterfacesList[i], Entry);
            if (!NT_SUCCESS(Status))
                goto Error;

            TRACE("Got entity %*s, index %u.\n",
                Entry->if_descrlen, &Entry->if_descr[0], Entry->if_index);

            /* Add the adapter name */
            CurrentAASize += Entry->if_descrlen + sizeof(CHAR);

            /* Add the DNS suffix */
            CurrentAASize += sizeof(WCHAR);

            /* Add the description. */
            CurrentAASize += sizeof(WCHAR);

            if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
            {
                /* Just an empty string for now. */
                FIXME("Should get adapter friendly name.\n");
                CurrentAASize += sizeof(WCHAR);
            }

            if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER))
            {
                /* Enumerate the name servers */
                HKEY InterfaceKey;
                CHAR KeyName[256];

                snprintf(KeyName, 256,
                    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
                    Entry->if_descrlen, &Entry->if_descr[0]);

                if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) != ERROR_SUCCESS)
                {
                    ERR("Failed opening interface key for interface %*s\n", Entry->if_descrlen, &Entry->if_descr[0]);
                    Flags |= GAA_FLAG_SKIP_DNS_SERVER;
                }
                else
                {
                    EnumNameServers(InterfaceKey, NULL, &CurrentAASize, EnumerateServerNameSize);
                    RegCloseKey(InterfaceKey);
                }
            }

            /* This is part of what we will need */
            TotalSize += CurrentAASize;

            /* Fill in the data */
            if ((CurrentAA) && (RemainingSize >= CurrentAASize))
            {
                CurrentAA->Length = sizeof(IP_ADAPTER_ADDRESSES);
                CurrentAA->IfIndex = Entry->if_index;
                CopyMemory(CurrentAA->PhysicalAddress, Entry->if_physaddr, Entry->if_physaddrlen);
                CurrentAA->PhysicalAddressLength = Entry->if_physaddrlen;
                CurrentAA->Flags = 0; // FIXME!
                CurrentAA->Mtu = Entry->if_mtu;
                CurrentAA->IfType = Entry->if_type;
                CurrentAA->OperStatus = Entry->if_operstatus;
                /* Next items */
                Ptr = (BYTE*)(CurrentAA + 1);

                /* Now fill in the name */
                CopyMemory(Ptr, &Entry->if_descr[0], Entry->if_descrlen);
                CurrentAA->AdapterName = (PCHAR)Ptr;
                CurrentAA->AdapterName[Entry->if_descrlen] = '\0';
                /* Next items */
                Ptr = (BYTE*)(CurrentAA->AdapterName + Entry->if_descrlen + 1);

                /* The DNS suffix */
                CurrentAA->DnsSuffix = (PWCHAR)Ptr;
                CurrentAA->DnsSuffix[0] = L'\0';
                /* Next items */
                Ptr = (BYTE*)(CurrentAA->DnsSuffix + 1);

                /* The description */
                CurrentAA->Description = (PWCHAR)Ptr;
                CurrentAA->Description[0] = L'\0';
                /* Next items */
                Ptr = (BYTE*)(CurrentAA->Description + 1);

                /* The friendly name */
                if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
                {
                    CurrentAA->FriendlyName = (PWCHAR)Ptr;
                    CurrentAA->FriendlyName[0] = L'\0';
                    /* Next items */
                    Ptr = (BYTE*)(CurrentAA->FriendlyName + 1);
                }

                /* The DNS Servers */
                if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER))
                {
                    /* Enumerate the name servers */
                    HKEY InterfaceKey;
                    CHAR KeyName[256];

                    snprintf(KeyName, 256,
                        "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
                        Entry->if_descrlen, &Entry->if_descr[0]);

                    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) != ERROR_SUCCESS)
                    {
                        ERR("Failed opening interface key for interface %*s\n", Entry->if_descrlen, &Entry->if_descr[0]);
                    }
                    else
                    {
                        PIP_ADAPTER_DNS_SERVER_ADDRESS* ServerAddressPtr;

                        CurrentAA->FirstDnsServerAddress = (PIP_ADAPTER_DNS_SERVER_ADDRESS)Ptr;
                        ServerAddressPtr = &CurrentAA->FirstDnsServerAddress;

                        EnumNameServers(InterfaceKey, NULL, &ServerAddressPtr, EnumerateServerName);
                        RegCloseKey(InterfaceKey);

                        /* Set the last entry in the list as having NULL next member */
                        Ptr = (BYTE*)*ServerAddressPtr;
                        *ServerAddressPtr = NULL;
                    }
                }

                /* We're done for this interface */
                PreviousAA = CurrentAA;
                RemainingSize -= CurrentAASize;
            }
        }
    }

    if (AdaptersCount == 0)
    {
        /* Uh? Not even localhost ?! */
        ERR("No Adapters found!\n");
        *pOutBufLen = 0;
        return ERROR_NO_DATA;
    }

    /* See if we have anything to add */
    // FIXME: Anycast and multicast
    if ((Flags & (GAA_FLAG_SKIP_UNICAST | GAA_FLAG_INCLUDE_PREFIX)) == GAA_FLAG_SKIP_UNICAST)
        goto Success;

    /* Now fill in the addresses */
    for (i = 0; i < InterfacesCount; i++)
    {
        /* Look for network layers */
        if ((InterfacesList[i].tei_entity == CL_NL_ENTITY)
                || (InterfacesList[i].tei_entity == CO_NL_ENTITY))
        {
            IPSNMPInfo SnmpInfo;
            PIP_ADAPTER_ADDRESSES CurrentAA = NULL;
            IPAddrEntry* AddrEntries;
            ULONG j;

            /* Get its SNMP info */
            Status = GetSnmpInfo(TcpFile, InterfacesList[i], &SnmpInfo);
            if (!NT_SUCCESS(Status))
                goto Error;

            if (SnmpInfo.ipsi_numaddr == 0)
                continue;

            /* Allocate the address entry array and get them */
            AddrEntries = HeapAlloc(GetProcessHeap(),
                HEAP_ZERO_MEMORY,
                SnmpInfo.ipsi_numaddr * sizeof(AddrEntries[0]));
            if (!AddrEntries)
            {
                Status = STATUS_NO_MEMORY;
                goto Error;
            }
            Status = GetAddrEntries(TcpFile, InterfacesList[i], AddrEntries, SnmpInfo.ipsi_numaddr);
            if (!NT_SUCCESS(Status))
            {
                HeapFree(GetProcessHeap(), 0, AddrEntries);
                goto Error;
            }

            for (j = 0; j < SnmpInfo.ipsi_numaddr; j++)
            {
                /* Find the adapters struct for this address. */
                if (pAdapterAddresses)
                {
                    CurrentAA = pAdapterAddresses;
                    while (CurrentAA)
                    {
                        if (CurrentAA->IfIndex == AddrEntries[j].iae_index)
                            break;

                        CurrentAA = CurrentAA->Next;
                    }

                    if (!CurrentAA)
                    {
                        ERR("Got address for interface %u but no adapter was found for it.\n", AddrEntries[j].iae_index);
                        /* Go to the next address */
                        continue;
                    }
                }

                ERR("address is 0x%08x, mask is 0x%08x\n", AddrEntries[j].iae_addr, AddrEntries[j].iae_mask);

                //FIXME: For now reactos only supports unicast addresses
                if (!(Flags & GAA_FLAG_SKIP_UNICAST))
                {
                    ULONG Size = sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR);

                    if (Ptr && (RemainingSize >= Size))
                    {
                        PIP_ADAPTER_UNICAST_ADDRESS UnicastAddress = (PIP_ADAPTER_UNICAST_ADDRESS)Ptr;

                        /* Fill in the structure */
                        UnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
                        UnicastAddress->Next = CurrentAA->FirstUnicastAddress;

                        // FIXME: Put meaningful value here
                        UnicastAddress->Flags = 0;
                        UnicastAddress->PrefixOrigin = IpPrefixOriginOther;
                        UnicastAddress->SuffixOrigin = IpSuffixOriginOther;
                        UnicastAddress->DadState = IpDadStatePreferred;
                        UnicastAddress->ValidLifetime = 0xFFFFFFFF;
                        UnicastAddress->PreferredLifetime = 0xFFFFFFFF;

                        /* Set the address */
                        //FIXME: ipv4 only (again...)
                        UnicastAddress->Address.lpSockaddr = (LPSOCKADDR)(UnicastAddress + 1);
                        UnicastAddress->Address.iSockaddrLength = sizeof(AddrEntries[j].iae_addr);
                        UnicastAddress->Address.lpSockaddr->sa_family = AF_INET;
                        memcpy(UnicastAddress->Address.lpSockaddr->sa_data, &AddrEntries[j].iae_addr, sizeof(AddrEntries[j].iae_addr));

                        CurrentAA->FirstUnicastAddress = UnicastAddress;
                        Ptr += Size;
                        RemainingSize -= Size;
                    }

                    TotalSize += Size;
                }

                if (Flags & GAA_FLAG_INCLUDE_PREFIX)
                {
                    ULONG Size = sizeof(IP_ADAPTER_PREFIX) + sizeof(SOCKADDR);

                    if (Ptr && (RemainingSize >= Size))
                    {
                        PIP_ADAPTER_PREFIX Prefix = (PIP_ADAPTER_PREFIX)Ptr;

                        /* Fill in the structure */
                        Prefix->Length = sizeof(IP_ADAPTER_PREFIX);
                        Prefix->Next = CurrentAA->FirstPrefix;

                        /* Set the address */
                        //FIXME: ipv4 only (again...)
                        Prefix->Address.lpSockaddr = (LPSOCKADDR)(Prefix + 1);
                        Prefix->Address.iSockaddrLength = sizeof(AddrEntries[j].iae_mask);
                        Prefix->Address.lpSockaddr->sa_family = AF_INET;
                        memcpy(Prefix->Address.lpSockaddr->sa_data, &AddrEntries[j].iae_mask, sizeof(AddrEntries[j].iae_mask));

                        /* Compute the prefix size */
                        _BitScanReverse(&Prefix->PrefixLength, AddrEntries[j].iae_mask);

                        CurrentAA->FirstPrefix = Prefix;
                        Ptr += Size;
                        RemainingSize -= Size;
                    }

                    TotalSize += Size;
                }
            }

            HeapFree(GetProcessHeap(), 0, AddrEntries);
        }
    }

Success:
    /* We're done */
    HeapFree(GetProcessHeap(), 0, InterfacesList);
    NtClose(TcpFile);
    *pOutBufLen = TotalSize;
    TRACE("TotalSize: %x\n", *pOutBufLen);
    return ERROR_SUCCESS;

Error:
    ERR("Failed! Status 0x%08x\n", Status);
    *pOutBufLen = 0;
    HeapFree(GetProcessHeap(), 0, InterfacesList);
    NtClose(TcpFile);
    return RtlNtStatusToDosError(Status);
}