Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140/* * 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@reactos.org) */
#include "iphlpapi_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);#ifdef GetAdaptersAddressesV2/* Helper for GetAdaptersAddresses: * Retrieves the list of network adapters from tcpip.sys */staticNTSTATUSGetInterfacesList( _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;}
staticNTSTATUSGetSnmpInfo( _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;}
staticNTSTATUSGetAddrEntries( _In_ HANDLE TcpFile, _In_ TDIEntityID InterfaceID, _Out_ IPAddrEntry* Entries, _In_ ULONG NumEntries){ 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_ADDRTABLE_ENTRY_ID; TcpQueryInfo.ID.toi_entity = InterfaceID;
Status = NtDeviceIoControlFile( TcpFile, NULL, NULL, NULL, &StatusBlock, IOCTL_TCP_QUERY_INFORMATION_EX, &TcpQueryInfo, sizeof(TcpQueryInfo), Entries, NumEntries * sizeof(Entries[0])); 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;}
/* * 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. ;-) */staticNTSTATUSGetInterfaceEntry( _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 */staticVOIDEnumerateServerNameSize( _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);}
staticVOIDEnumerateServerName( _In_ PWCHAR Interface, _In_ PWCHAR NameServer, _Inout_ PVOID Data){ PIP_ADAPTER_DNS_SERVER_ADDRESS** Ptr = Data; PIP_ADAPTER_DNS_SERVER_ADDRESS ServerAddress = **Ptr; PCWSTR Terminator; NTSTATUS Status;
UNREFERENCED_PARAMETER(Interface);
ServerAddress->Length = sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS); ServerAddress->Address.lpSockaddr = (PVOID)(ServerAddress + 1); ServerAddress->Address.iSockaddrLength = sizeof(SOCKADDR);
ServerAddress->Address.lpSockaddr->sa_family = AF_INET; ((LPSOCKADDR_IN)ServerAddress->Address.lpSockaddr)->sin_port = 0;
Status = RtlIpv4StringToAddressW(NameServer, FALSE, &Terminator, &((LPSOCKADDR_IN)ServerAddress->Address.lpSockaddr)->sin_addr); if (!NT_SUCCESS(Status)) { /* 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;}
staticVOIDQueryFlags( _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}
staticULONGCountPrefixBits( _In_ ULONG Netmask){ ULONG i, BitCount = 0;
for (i = 0; i < sizeof(ULONG) * 8; i++) { if ((Netmask & (1 << i)) == 0) break; BitCount++; }
return BitCount;}
DWORDWINAPIDECLSPEC_HOTPATCHGetAdaptersAddresses( _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;
TRACE("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; ULONG FriendlySize = 0, DescriptionSize = 0; ULONG DhcpDomainSize = 0, DomainSize = 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 */ if (Entry->if_type != IF_TYPE_SOFTWARE_LOOPBACK) { HKEY InterfaceKey; CHAR KeyName[256]; DWORD ValueType, ValueSize, Data;
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) { ValueSize = sizeof(DWORD); if (RegQueryValueExW(InterfaceKey, L"EnableDHCP", NULL, &ValueType, (LPBYTE)&Data, &ValueSize) == ERROR_SUCCESS && ValueType == REG_DWORD && Data == 1) { ValueSize = sizeof(DWORD); if (RegQueryValueExW(InterfaceKey, L"DhcpDomain", NULL, &ValueType, NULL, &ValueSize) == ERROR_SUCCESS && ValueType == REG_SZ) { /* We remove the null char, it will be re-added after */ DhcpDomainSize = ValueSize - sizeof(WCHAR); CurrentAASize += DhcpDomainSize; } } else { ValueSize = sizeof(DWORD); if (RegQueryValueExW(InterfaceKey, L"Domain", NULL, &ValueType, NULL, &ValueSize) == ERROR_SUCCESS && ValueType == REG_SZ) { /* We remove the null char, it will be re-added after */ DomainSize = ValueSize - sizeof(WCHAR); CurrentAASize += DomainSize; } }
RegCloseKey(InterfaceKey); } }
CurrentAASize += sizeof(WCHAR);
/* Add the description. */ if (Entry->if_type == IF_TYPE_SOFTWARE_LOOPBACK) { DescriptionSize = mbstowcs(NULL, (PCSTR)&Entry->if_descr[0], Entry->if_descrlen) * sizeof(WCHAR); CurrentAASize += DescriptionSize; } else { HKEY ConnectionKey; CHAR KeyName[256]; CHAR InstanceID[128]; DWORD ValueType = 0; DWORD ValueSize = 0;
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) { ValueSize = 128; RegQueryValueExA(ConnectionKey, "PnpInstanceID", NULL, &ValueType, (LPBYTE)InstanceID, &ValueSize); RegCloseKey(ConnectionKey); }
if (ValueSize != 0) { sprintf(KeyName, "SYSTEM\\CurrentControlSet\\Enum\\%s", InstanceID);
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &ConnectionKey) == ERROR_SUCCESS) { ValueSize = 0; if (RegQueryValueExW(ConnectionKey, L"DeviceDesc", NULL, &ValueType, NULL, &ValueSize) == ERROR_SUCCESS && ValueType == REG_SZ) { /* We remove the null char, it will be re-added after */ DescriptionSize = ValueSize - sizeof(WCHAR); CurrentAASize += DescriptionSize; }
RegCloseKey(ConnectionKey); } } }
/* We always make sure to have enough room for empty string */ CurrentAASize += sizeof(WCHAR);
if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) { if (Entry->if_type == IF_TYPE_SOFTWARE_LOOPBACK) { FriendlySize = mbstowcs(NULL, (PCSTR)&Entry->if_descr[0], Entry->if_descrlen) * sizeof(WCHAR); CurrentAASize += FriendlySize; } else { /* 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); }
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) { 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; QueryFlags(&Entry->if_descr[0], Entry->if_descrlen, &CurrentAA->Flags); CurrentAA->Mtu = Entry->if_mtu; CurrentAA->IfType = Entry->if_type; if(Entry->if_operstatus >= IF_OPER_STATUS_CONNECTING) CurrentAA->OperStatus = IfOperStatusUp; else CurrentAA->OperStatus = IfOperStatusDown;
/* 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;
if (Entry->if_type != IF_TYPE_SOFTWARE_LOOPBACK) { HKEY InterfaceKey; CHAR KeyName[256]; DWORD ValueType, ValueSize;
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) { if (DhcpDomainSize != 0) { ValueSize = DhcpDomainSize + sizeof(WCHAR); if (RegQueryValueExW(InterfaceKey, L"DhcpDomain", NULL, &ValueType, (LPBYTE)CurrentAA->DnsSuffix, &ValueSize) == ERROR_SUCCESS && ValueType == REG_SZ && ValueSize == DhcpDomainSize + sizeof(WCHAR)) { /* We're done, next items */ Ptr = (BYTE*)(CurrentAA->DnsSuffix + (ValueSize / sizeof(WCHAR))); } else { /* Fail */ ERR("DhcpDomain name changed after probe!\n"); DhcpDomainSize = 0; } }
if (DomainSize != 0) { ValueSize = DomainSize + sizeof(WCHAR); if (RegQueryValueExW(InterfaceKey, L"Domain", NULL, &ValueType, (LPBYTE)CurrentAA->DnsSuffix, &ValueSize) == ERROR_SUCCESS && ValueType == REG_SZ && ValueSize == DomainSize + sizeof(WCHAR)) { /* We're done, next items */ Ptr = (BYTE*)(CurrentAA->DnsSuffix + (ValueSize / sizeof(WCHAR))); } else { /* Fail */ ERR("Domain name changed after probe!\n"); DomainSize = 0; } }
RegCloseKey(InterfaceKey); } }
/* In case of failure (or no name) */ if ((DhcpDomainSize == 0) && (DomainSize == 0)) { CurrentAA->DnsSuffix[0] = L'\0'; /* Next items */ Ptr = (BYTE*)(CurrentAA->DnsSuffix + 1); }
/* The description */ CurrentAA->Description = (PWCHAR)Ptr;
if (DescriptionSize != 0) { if (Entry->if_type == IF_TYPE_SOFTWARE_LOOPBACK) { size_t size; size = mbstowcs((PWCHAR)Ptr, (PCSTR)&Entry->if_descr[0], Entry->if_descrlen); CurrentAA->Description = (PWCHAR)Ptr; CurrentAA->Description[size] = '\0'; /* Next items */ Ptr = (BYTE*)(CurrentAA->Description + size + 1); } else { HKEY ConnectionKey; CHAR KeyName[256]; CHAR InstanceID[128]; DWORD ValueType = 0; DWORD ValueSize = 0;
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) { ValueSize = 128; RegQueryValueExA(ConnectionKey, "PnpInstanceID", NULL, &ValueType, (LPBYTE)InstanceID, &ValueSize); RegCloseKey(ConnectionKey); }
if (ValueSize != 0) { sprintf(KeyName, "SYSTEM\\CurrentControlSet\\Enum\\%s", InstanceID);
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &ConnectionKey) == ERROR_SUCCESS) { ValueSize = DescriptionSize + sizeof(WCHAR); if (RegQueryValueExW(ConnectionKey, L"DeviceDesc", NULL, &ValueType, (LPBYTE)CurrentAA->Description, &ValueSize) == ERROR_SUCCESS && ValueType == REG_SZ && ValueSize == DescriptionSize + sizeof(WCHAR)) { /* We're done, next items */ Ptr = (BYTE*)(CurrentAA->Description + (ValueSize / sizeof(WCHAR))); } else { /* Fail */ ERR("Description name changed after probe!\n"); DescriptionSize = 0; }
RegCloseKey(ConnectionKey); } } } }
/* In case of failure (or no name) */ if (DescriptionSize == 0) { 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;
if (FriendlySize != 0) { /* Get the friendly name */ if (Entry->if_type == IF_TYPE_SOFTWARE_LOOPBACK) { size_t size; size = mbstowcs(CurrentAA->FriendlyName, (PCSTR)&Entry->if_descr[0], Entry->if_descrlen); CurrentAA->FriendlyName[size] = '\0'; /* Next items */ Ptr = (BYTE*)(CurrentAA->FriendlyName + size + 1); } else { 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 (!(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) { TRACE("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; } }
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)) { 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(SOCKADDR); UnicastAddress->Address.lpSockaddr->sa_family = AF_INET; ((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_port = 0; ((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_addr.S_un.S_addr = 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(SOCKADDR); Prefix->Address.lpSockaddr->sa_family = AF_INET; ((LPSOCKADDR_IN)Prefix->Address.lpSockaddr)->sin_port = 0; ((LPSOCKADDR_IN)Prefix->Address.lpSockaddr)->sin_addr.S_un.S_addr = AddrEntries[j].iae_addr & AddrEntries[j].iae_mask;
/* Compute the prefix size */ Prefix->PrefixLength = CountPrefixBits(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);}
DWORDWINAPINhpAllocateAndGetInterfaceInfoFromStack( _Inout_ IP_INTERFACE_NAME_INFO **ppTable, _Inout_ PDWORD pdwCount, _In_ BOOL bOrder, _In_ HANDLE hHeap, _In_ DWORD dwFlags){ NTSTATUS Status; HANDLE TcpFile; TDIEntityID* InterfacesList; ULONG InterfacesCount; ULONG AdaptersCount = 0; ULONG i, j; IP_INTERFACE_NAME_INFO *pTable = NULL; UNICODE_STRING UnicodeGuidString; ANSI_STRING AnsiGuidString;
TRACE("ppTable %p, pdwCount %p, bOrder %u, hHeap %p, dwFlags %lu\n", ppTable, pdwCount, bOrder, hHeap, dwFlags);
/* 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); }
for (i = 0; i < InterfacesCount; i++) { 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;
/* Get the entry */ Status = GetInterfaceEntry(TcpFile, InterfacesList[i], Entry); if (!NT_SUCCESS(Status)) goto Error;
if (Entry->if_type != IF_TYPE_SOFTWARE_LOOPBACK) AdaptersCount++; } }
TRACE("InterfacesCount %lu AdaptersCount %lu\n", InterfacesCount, AdaptersCount);
pTable = HeapAlloc(hHeap, dwFlags, AdaptersCount * sizeof(IP_INTERFACE_NAME_INFO)); if (pTable == NULL) { Status = STATUS_NO_MEMORY; goto Error; }
for (i = 0, j = 0; i < InterfacesCount; i++) { 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;
/* 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);
if (Entry->if_type != IF_TYPE_SOFTWARE_LOOPBACK) { pTable[j].Index = Entry->if_index; pTable[j].MediaType = Entry->if_type; pTable[j].ConnectionType = 1; //IF_CONNECTION_DEDICATED; pTable[j].AccessType = 2; //IF_ACCESS_BROADCAST;
AnsiGuidString.Length = Entry->if_descrlen; AnsiGuidString.MaximumLength = Entry->if_descrlen; AnsiGuidString.Buffer = (PCHAR)Entry->if_descr; Status = RtlAnsiStringToUnicodeString(&UnicodeGuidString, &AnsiGuidString, TRUE); if (!NT_SUCCESS(Status)) { ERR("Status %lx\n", Status); goto Error; }
Status = RtlGUIDFromString(&UnicodeGuidString, &pTable[j].DeviceGuid); RtlFreeUnicodeString(&UnicodeGuidString); if (!NT_SUCCESS(Status)) { ERR("Status %lx\n", Status); goto Error; }
memset(&pTable[j].InterfaceGuid, 0, sizeof(GUID));
j++; } } }
/* We're done */ HeapFree(GetProcessHeap(), 0, InterfacesList); NtClose(TcpFile); *ppTable = pTable; *pdwCount = AdaptersCount; return ERROR_SUCCESS;
Error: ERR("Failed! Status 0x%08x\n", Status); if (pTable) HeapFree(hHeap, 0, pTable); *ppTable = NULL; *pdwCount = 0; HeapFree(GetProcessHeap(), 0, InterfacesList); NtClose(TcpFile); return RtlNtStatusToDosError(Status);}
#endif