Author: jgardou
Date: Mon Nov 3 12:55:59 2014
New Revision: 65220
URL:
http://svn.reactos.org/svn/reactos?rev=65220&view=rev
Log:
[IPHLPAPI]
- Start implementing GetAdaptersAddresses.
For now it noly gives interface names and DNS servers IP, but that's already more than
'UNIMPLEMENTED'.
Added:
trunk/reactos/dll/win32/iphlpapi/address.c (with props)
Modified:
trunk/reactos/dll/win32/iphlpapi/CMakeLists.txt
trunk/reactos/dll/win32/iphlpapi/iphlpapi_main.c
Modified: trunk/reactos/dll/win32/iphlpapi/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/iphlpapi/CMakeLi…
==============================================================================
--- trunk/reactos/dll/win32/iphlpapi/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/iphlpapi/CMakeLists.txt [iso-8859-1] Mon Nov 3 12:55:59 2014
@@ -7,6 +7,7 @@
spec2def(iphlpapi.dll iphlpapi.spec ADD_IMPORTLIB)
list(APPEND SOURCE
+ address.c
dhcp_reactos.c
ifenum_reactos.c
ipstats_reactos.c
Added: trunk/reactos/dll/win32/iphlpapi/address.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/iphlpapi/address…
==============================================================================
--- trunk/reactos/dll/win32/iphlpapi/address.c (added)
+++ trunk/reactos/dll/win32/iphlpapi/address.c [iso-8859-1] Mon Nov 3 12:55:59 2014
@@ -0,0 +1,514 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: dll/win32/iphlpapi/address.c
+ * PURPOSE: iphlpapi implementation - Adapter Address APIs
+ * PROGRAMMERS: Jérôme Gardou (jerome.gardou(a)reactos.org)
+ */
+
+#include "iphlpapi_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
+
+/* Helper for GetAdaptersAddresses:
+ * Retrieves the list of network adapters from tcpip.sys */
+static
+NTSTATUS
+GetInterfacesList(
+ _In_ HANDLE TcpFile,
+ _Out_ TDIEntityID **EntityList,
+ _Out_ ULONG* InterfaceCount)
+{
+
+ TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo;
+ IO_STATUS_BLOCK StatusBlock;
+ NTSTATUS Status;
+ ULONG_PTR BufferSize;
+
+ ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo));
+ TcpQueryInfo.ID.toi_class = INFO_CLASS_GENERIC;
+ TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER;
+ TcpQueryInfo.ID.toi_id = ENTITY_LIST_ID;
+ TcpQueryInfo.ID.toi_entity.tei_entity = GENERIC_ENTITY;
+ TcpQueryInfo.ID.toi_entity.tei_instance = 0;
+
+ Status = NtDeviceIoControlFile(
+ TcpFile,
+ NULL,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &TcpQueryInfo,
+ sizeof(TcpQueryInfo),
+ NULL,
+ 0);
+ if (Status == STATUS_PENDING)
+ {
+ /* So we have to wait a bit */
+ Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
+ if (NT_SUCCESS(Status))
+ Status = StatusBlock.Status;
+ }
+
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ BufferSize = StatusBlock.Information;
+ *EntityList = HeapAlloc(GetProcessHeap(), 0, BufferSize);
+ if (!*EntityList)
+ return STATUS_NO_MEMORY;
+
+ /* Do the real call */
+ Status = NtDeviceIoControlFile(
+ TcpFile,
+ NULL,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &TcpQueryInfo,
+ sizeof(TcpQueryInfo),
+ *EntityList,
+ BufferSize);
+ if (Status == STATUS_PENDING)
+ {
+ /* So we have to wait a bit */
+ Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
+ if (NT_SUCCESS(Status))
+ Status = StatusBlock.Status;
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ HeapFree(GetProcessHeap(), 0, *EntityList);
+ return Status;
+ }
+
+ *InterfaceCount = BufferSize / sizeof(TDIEntityID);
+ return Status;
+}
+
+#if 0
+static
+NTSTATUS
+GetSnmpInfo(
+ _In_ HANDLE TcpFile,
+ _In_ TDIEntityID InterfaceID,
+ _Out_ IPSNMPInfo* Info)
+{
+ TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo;
+ IO_STATUS_BLOCK StatusBlock;
+ NTSTATUS Status;
+
+ ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo));
+ TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL;
+ TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER;
+ TcpQueryInfo.ID.toi_id = IP_MIB_STATS_ID;
+ TcpQueryInfo.ID.toi_entity = InterfaceID;
+
+ Status = NtDeviceIoControlFile(
+ TcpFile,
+ NULL,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &TcpQueryInfo,
+ sizeof(TcpQueryInfo),
+ Info,
+ sizeof(*Info));
+ if (Status == STATUS_PENDING)
+ {
+ /* So we have to wait a bit */
+ Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
+ if (NT_SUCCESS(Status))
+ Status = StatusBlock.Status;
+ }
+
+ return Status;
+}
+#endif
+
+/*
+ * Fills the IFEntry buffer from tcpip.sys.
+ * The buffer size MUST be FIELD_OFFSET(IFEntry, if_descr[MAX_ADAPTER_DESCRIPTION_LENGTH
+ 1]).
+ * See MSDN IFEntry struct definition if you don't believe me. ;-)
+ */
+static
+NTSTATUS
+GetInterfaceEntry(
+ _In_ HANDLE TcpFile,
+ _In_ TDIEntityID InterfaceID,
+ _Out_ IFEntry* Entry)
+{
+ TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo;
+ IO_STATUS_BLOCK StatusBlock;
+ NTSTATUS Status;
+
+ ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo));
+ TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL;
+ TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER;
+ TcpQueryInfo.ID.toi_id = IP_MIB_STATS_ID;
+ TcpQueryInfo.ID.toi_entity = InterfaceID;
+
+ Status = NtDeviceIoControlFile(
+ TcpFile,
+ NULL,
+ NULL,
+ NULL,
+ &StatusBlock,
+ IOCTL_TCP_QUERY_INFORMATION_EX,
+ &TcpQueryInfo,
+ sizeof(TcpQueryInfo),
+ Entry,
+ FIELD_OFFSET(IFEntry, if_descr[MAX_ADAPTER_DESCRIPTION_LENGTH + 1]));
+ if (Status == STATUS_PENDING)
+ {
+ /* So we have to wait a bit */
+ Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
+ if (NT_SUCCESS(Status))
+ Status = StatusBlock.Status;
+ }
+
+ return Status;
+}
+
+/* Helpers to get the list of DNS for an interface */
+static
+VOID
+EnumerateServerNameSize(
+ _In_ PWCHAR Interface,
+ _In_ PWCHAR NameServer,
+ _Inout_ PVOID Data)
+{
+ ULONG* BufferSize = Data;
+
+ /* This is just sizing here */
+ UNREFERENCED_PARAMETER(Interface);
+ UNREFERENCED_PARAMETER(NameServer);
+
+ *BufferSize += sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS) + sizeof(SOCKADDR);
+}
+
+static
+VOID
+EnumerateServerName(
+ _In_ PWCHAR Interface,
+ _In_ PWCHAR NameServer,
+ _Inout_ PVOID Data)
+{
+ PIP_ADAPTER_DNS_SERVER_ADDRESS** Ptr = Data;
+ PIP_ADAPTER_DNS_SERVER_ADDRESS ServerAddress = **Ptr;
+
+ UNREFERENCED_PARAMETER(Interface);
+
+ ServerAddress->Length = sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS);
+ ServerAddress->Address.lpSockaddr = (PVOID)(ServerAddress + 1);
+ ServerAddress->Address.iSockaddrLength = sizeof(SOCKADDR);
+
+
+ /* Get the address from the server name string */
+ //FIXME: Only ipv4 for now...
+ if (WSAStringToAddressW(
+ NameServer,
+ AF_INET,
+ NULL,
+ ServerAddress->Address.lpSockaddr,
+ &ServerAddress->Address.iSockaddrLength))
+ {
+ /* Pass along, name conversion failed */
+ ERR("%S is not a valid IP address\n", NameServer);
+ return;
+ }
+
+ /* Go to next item */
+ ServerAddress->Next = (PVOID)(ServerAddress->Address.lpSockaddr + 1);
+ *Ptr = &ServerAddress->Next;
+}
+
+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;
+
+ 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;
+
+ if ((Family == AF_INET6) || (Family == AF_UNSPEC))
+ {
+ /* One day maybe... */
+ FIXME("IPv6 is not supported in ReactOS!\n");
+ if (Family == AF_INET6)
+ {
+ /* We got nothing to say in this case */
+ return ERROR_NO_DATA;
+ }
+ }
+
+ RemainingSize = *pOutBufLen;
+ if (Ptr)
+ ZeroMemory(Ptr, RemainingSize);
+
+ /* open the tcpip driver */
+ Status = openTcpFile(&TcpFile);
+ 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, PreviousAA = NULL;
+ ULONG CurrentAASize = 0;
+
+ if (InterfacesList[i].tei_entity == IF_ENTITY)
+ {
+ BYTE EntryBuffer[FIELD_OFFSET(IFEntry,
if_descr[MAX_ADAPTER_DESCRIPTION_LENGTH + 1])];
+ IFEntry* Entry = (IFEntry*)EntryBuffer;
+
+ /* Remember we got one */
+ AdaptersCount++;
+
+ /* 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;
+ CurrentAA->Next = PreviousAA;
+ /* 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;
+ }
+
+/* Disabled for now until someone knows how to differentiate unicast/multicast whatver
adresses */
+#if 0
+ /* See what we will fill our buffer with */
+ for (i = 0; i < InterfacesCount; i++)
+ {
+ /* Look for network layers */
+ if ((InterfacesList[i].tei_entity == CL_TL_ENTITY)
+ || (InterfacesList[i].tei_entity == CO_TL_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;
+
+ /* 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;
+ }
+
+ 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;
+ }
+ }
+ }
+
+ }
+ }
+#endif
+
+ /* We're done */
+ HeapFree(GetProcessHeap(), 0, InterfacesList);
+ NtClose(TcpFile);
+ *pOutBufLen = TotalSize;
+ return ERROR_SUCCESS;
+
+Error:
+ ERR("Failed! Status 0x%08x\n", Status);
+ *pOutBufLen = 0;
+ HeapFree(GetProcessHeap(), 0, InterfacesList);
+ NtClose(TcpFile);
+ return RtlNtStatusToDosError(Status);
+}
Propchange: trunk/reactos/dll/win32/iphlpapi/address.c
------------------------------------------------------------------------------
charset = UTF-8
Propchange: trunk/reactos/dll/win32/iphlpapi/address.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/reactos/dll/win32/iphlpapi/address.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: trunk/reactos/dll/win32/iphlpapi/iphlpapi_main.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/iphlpapi/iphlpap…
==============================================================================
--- trunk/reactos/dll/win32/iphlpapi/iphlpapi_main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/iphlpapi/iphlpapi_main.c [iso-8859-1] Mon Nov 3 12:55:59
2014
@@ -2281,9 +2281,9 @@
/*
* @implemented
*/
+#if 0
DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID
Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
{
-#if 0
InterfaceIndexTable *indexTable;
IFInfo ifInfo;
int i;
@@ -2470,16 +2470,8 @@
free(indexTable);
return NO_ERROR;
-#else
- if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
- if (!pAdapterAddresses || *pOutBufLen == 0)
- return ERROR_BUFFER_OVERFLOW;
- if (Reserved) return ERROR_INVALID_PARAMETER;
-
- FIXME(":stub\n");
- return ERROR_NO_DATA;
+}
#endif
-}
/*
* @unimplemented