#include "iphlpapi_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
-
+#ifdef GetAdaptersAddressesV2
/* Helper for GetAdaptersAddresses:
* Retrieves the list of network adapters from tcpip.sys */
static
*Ptr = &ServerAddress->Next;
}
+static
+VOID
+QueryFlags(
+ _In_ PUCHAR Interface,
+ _In_ DWORD InterfaceLength,
+ _Out_ LPDWORD Flags)
+{
+ HKEY InterfaceKey;
+ CHAR KeyName[256];
+ DWORD Type, Size, Data;
+
+ *Flags = 0;
+
+ snprintf(KeyName, 256,
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
+ InterfaceLength, Interface);
+
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) == ERROR_SUCCESS)
+ {
+ Size = sizeof(DWORD);
+ if (RegQueryValueExA(InterfaceKey, "EnableDHCP", NULL, &Type, (LPBYTE)&Data, &Size) == ERROR_SUCCESS &&
+ Type == REG_DWORD && Data == 1)
+ {
+ *Flags |= IP_ADAPTER_DHCP_ENABLED;
+ }
+
+ Size = sizeof(DWORD);
+ if (RegQueryValueExA(InterfaceKey, "RegisterAdapterName", NULL, &Type, (LPBYTE)&Data, &Size) == ERROR_SUCCESS &&
+ Type == REG_DWORD && Data == 1)
+ {
+ *Flags |= IP_ADAPTER_REGISTER_ADAPTER_SUFFIX;
+ }
+
+ Size = 0;
+ if (RegQueryValueExA(InterfaceKey, "NameServer", NULL, &Type, (LPBYTE)&Data, &Size) != ERROR_SUCCESS)
+ {
+ *Flags |= IP_ADAPTER_DDNS_ENABLED;
+ }
+
+ RegCloseKey(InterfaceKey);
+ }
+
+ // FIXME: handle 0x8 -> 0x20
+}
+
DWORD
WINAPI
DECLSPEC_HOTPATCH
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);
+ TRACE("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))
+ // 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)
{
- /* One day maybe... */
- FIXME("IPv6 is not supported in ReactOS!\n");
- if (Family == AF_INET6)
- {
+ *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;
ZeroMemory(Ptr, RemainingSize);
/* open the tcpip driver */
- Status = openTcpFile(&TcpFile);
+ Status = openTcpFile(&TcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(Status))
{
ERR("Could not open handle to tcpip.sys. Status %08x\n", 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;
+ PIP_ADAPTER_ADDRESSES CurrentAA = (PIP_ADAPTER_ADDRESSES)Ptr;
ULONG CurrentAASize = 0;
+ ULONG FriendlySize = 0;
if (InterfacesList[i].tei_entity == IF_ENTITY)
{
/* 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);
if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
{
- /* Just an empty string for now. */
- FIXME("Should get adapter friendly name.\n");
+ /* Get the friendly name */
+ HKEY ConnectionKey;
+ CHAR KeyName[256];
+
+ snprintf(KeyName, 256,
+ "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%*s\\Connection",
+ Entry->if_descrlen, &Entry->if_descr[0]);
+
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &ConnectionKey) == ERROR_SUCCESS)
+ {
+ DWORD ValueType;
+ DWORD ValueSize = 0;
+
+ if (RegQueryValueExW(ConnectionKey, L"Name", NULL, &ValueType, NULL, &ValueSize) == ERROR_SUCCESS &&
+ ValueType == REG_SZ)
+ {
+ /* We remove the null char, it will be re-added after */
+ FriendlySize = ValueSize - sizeof(WCHAR);
+ CurrentAASize += FriendlySize;
+ }
+
+ RegCloseKey(ConnectionKey);
+ }
+
+ /* We always make sure to have enough room for empty string */
CurrentAASize += sizeof(WCHAR);
}
"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
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) == ERROR_SUCCESS)
{
EnumNameServers(InterfaceKey, NULL, &CurrentAASize, EnumerateServerNameSize);
RegCloseKey(InterfaceKey);
CurrentAA->IfIndex = Entry->if_index;
CopyMemory(CurrentAA->PhysicalAddress, Entry->if_physaddr, Entry->if_physaddrlen);
CurrentAA->PhysicalAddressLength = Entry->if_physaddrlen;
- CurrentAA->Flags = 0; // FIXME!
+ QueryFlags(&Entry->if_descr[0], Entry->if_descrlen, &CurrentAA->Flags);
CurrentAA->Mtu = Entry->if_mtu;
CurrentAA->IfType = Entry->if_type;
- CurrentAA->OperStatus = Entry->if_operstatus;
- CurrentAA->Next = PreviousAA;
+ if(Entry->if_operstatus >= IF_OPER_STATUS_CONNECTING)
+ CurrentAA->OperStatus = IfOperStatusUp;
+ else
+ CurrentAA->OperStatus = IfOperStatusDown;
+
/* Next items */
Ptr = (BYTE*)(CurrentAA + 1);
if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
{
CurrentAA->FriendlyName = (PWCHAR)Ptr;
- CurrentAA->FriendlyName[0] = L'\0';
- /* Next items */
- Ptr = (BYTE*)(CurrentAA->FriendlyName + 1);
+
+ if (FriendlySize != 0)
+ {
+ /* Get the friendly name */
+ HKEY ConnectionKey;
+ CHAR KeyName[256];
+
+ snprintf(KeyName, 256,
+ "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%*s\\Connection",
+ Entry->if_descrlen, &Entry->if_descr[0]);
+
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &ConnectionKey) == ERROR_SUCCESS)
+ {
+ DWORD ValueType;
+ DWORD ValueSize = FriendlySize + sizeof(WCHAR);
+
+ if (RegQueryValueExW(ConnectionKey, L"Name", NULL, &ValueType, (LPBYTE)CurrentAA->FriendlyName, &ValueSize) == ERROR_SUCCESS &&
+ ValueType == REG_SZ && ValueSize == FriendlySize + sizeof(WCHAR))
+ {
+ /* We're done, next items */
+ Ptr = (BYTE*)(CurrentAA->FriendlyName + (ValueSize / sizeof(WCHAR)));
+ }
+ else
+ {
+ /* Fail */
+ ERR("Friendly name changed after probe!\n");
+ FriendlySize = 0;
+ }
+
+ RegCloseKey(ConnectionKey);
+ }
+ else
+ {
+ /* Fail */
+ FriendlySize = 0;
+ }
+ }
+
+ /* In case of failure (or no name) */
+ if (FriendlySize == 0)
+ {
+ CurrentAA->FriendlyName[0] = L'\0';
+ /* Next items */
+ Ptr = (BYTE*)(CurrentAA->FriendlyName + 1);
+ }
}
/* The DNS Servers */
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]);
+ TRACE("Failed opening interface key for interface %*s\n", Entry->if_descrlen, &Entry->if_descr[0]);
}
else
{
{
if (CurrentAA->IfIndex == AddrEntries[j].iae_index)
break;
+
+ CurrentAA = CurrentAA->Next;
}
if (!CurrentAA)
}
}
- ERR("address is 0x%08x, mask is 0x%08x\n", AddrEntries[j].iae_addr, AddrEntries[j].iae_mask);
+ TRACE("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))
/* Set the address */
//FIXME: ipv4 only (again...)
UnicastAddress->Address.lpSockaddr = (LPSOCKADDR)(UnicastAddress + 1);
- UnicastAddress->Address.iSockaddrLength = sizeof(AddrEntries[j].iae_addr);
+ UnicastAddress->Address.iSockaddrLength = sizeof(SOCKADDR);
UnicastAddress->Address.lpSockaddr->sa_family = AF_INET;
- memcpy(UnicastAddress->Address.lpSockaddr->sa_data, &AddrEntries[j].iae_addr, sizeof(AddrEntries[j].iae_addr));
+ ((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_port = 0;
+ memcpy(&((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_addr, &AddrEntries[j].iae_addr, sizeof(AddrEntries[j].iae_addr));
CurrentAA->FirstUnicastAddress = UnicastAddress;
Ptr += Size;
HeapFree(GetProcessHeap(), 0, InterfacesList);
NtClose(TcpFile);
*pOutBufLen = TotalSize;
+ TRACE("TotalSize: %x\n", *pOutBufLen);
return ERROR_SUCCESS;
Error:
NtClose(TcpFile);
return RtlNtStatusToDosError(Status);
}
+#endif