2 * iphlpapi dll implementation
4 * Copyright (C) 2003 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/types.h>
26 #ifdef HAVE_NETINET_IN_H
27 # include <netinet/in.h>
29 #ifdef HAVE_ARPA_INET_H
30 # include <arpa/inet.h>
32 #ifdef HAVE_ARPA_NAMESER_H
33 # include <arpa/nameser.h>
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
49 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
52 case DLL_PROCESS_ATTACH:
53 DisableThreadLibraryCalls( hinstDLL );
57 case DLL_PROCESS_DETACH:
64 /******************************************************************
65 * AddIPAddress (IPHLPAPI.@)
74 * NTEInstance [In/Out]
81 DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance)
84 /* marking Win2K+ functions not supported */
85 return ERROR_NOT_SUPPORTED;
89 /******************************************************************
90 * AllocateAndGetIfTableFromStack (IPHLPAPI.@)
95 * ppIfTable [Out] -- pointer into which the MIB_IFTABLE is
96 * allocated and returned.
97 * bOrder [In] -- passed to GetIfTable to order the table
98 * heap [In] -- heap from which the table is allocated
99 * flags [In] -- flags to HeapAlloc
101 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
102 * GetIfTable returns otherwise
105 DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable,
106 BOOL bOrder, HANDLE heap, DWORD flags)
110 TRACE("ppIfTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n", ppIfTable,
111 (DWORD)bOrder, (DWORD)heap, flags);
113 ret = ERROR_INVALID_PARAMETER;
117 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
118 if (ret == ERROR_INSUFFICIENT_BUFFER) {
119 *ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize);
120 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
123 TRACE("returning %ld\n", ret);
128 /******************************************************************
129 * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@)
134 * ppIpAddrTable [Out]
135 * bOrder [In] -- passed to GetIpAddrTable to order the table
136 * heap [In] -- heap from which the table is allocated
137 * flags [In] -- flags to HeapAlloc
144 DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
145 BOOL bOrder, HANDLE heap, DWORD flags)
149 TRACE("ppIpAddrTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
150 ppIpAddrTable, (DWORD)bOrder, (DWORD)heap, flags);
152 ret = ERROR_INVALID_PARAMETER;
156 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
157 if (ret == ERROR_INSUFFICIENT_BUFFER) {
158 *ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize);
159 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
162 TRACE("returning %ld\n", ret);
167 /******************************************************************
168 * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
171 * ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is
172 * allocated and returned.
173 * bOrder [In] -- passed to GetIfTable to order the table
174 * heap [In] -- heap from which the table is allocated
175 * flags [In] -- flags to HeapAlloc
177 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
178 * GetIpForwardTable returns otherwise
181 DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *
182 ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags)
186 TRACE("ppIpForwardTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
187 ppIpForwardTable, (DWORD)bOrder, (DWORD)heap, flags);
188 if (!ppIpForwardTable)
189 ret = ERROR_INVALID_PARAMETER;
193 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
194 if (ret == ERROR_INSUFFICIENT_BUFFER) {
195 *ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize);
196 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
199 TRACE("returning %ld\n", ret);
204 /******************************************************************
205 * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@)
211 * bOrder [In] -- passed to GetIpNetTable to order the table
212 * heap [In] -- heap from which the table is allocated
213 * flags [In] -- flags to HeapAlloc
220 DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable,
221 BOOL bOrder, HANDLE heap, DWORD flags)
225 TRACE("ppIpNetTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
226 ppIpNetTable, (DWORD)bOrder, (DWORD)heap, flags);
228 ret = ERROR_INVALID_PARAMETER;
232 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
233 if (ret == ERROR_INSUFFICIENT_BUFFER) {
234 *ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize);
235 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
238 TRACE("returning %ld\n", ret);
243 /******************************************************************
244 * AllocateAndGetTcpTableFromStack (IPHLPAPI.@)
250 * bOrder [In] -- passed to GetTcpTable to order the table
251 * heap [In] -- heap from which the table is allocated
252 * flags [In] -- flags to HeapAlloc
259 DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
260 BOOL bOrder, HANDLE heap, DWORD flags)
264 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
265 ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags);
267 ret = ERROR_INVALID_PARAMETER;
271 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
272 if (ret == ERROR_INSUFFICIENT_BUFFER) {
273 *ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize);
274 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
277 TRACE("returning %ld\n", ret);
282 /******************************************************************
283 * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
289 * bOrder [In] -- passed to GetUdpTable to order the table
290 * heap [In] -- heap from which the table is allocated
291 * flags [In] -- flags to HeapAlloc
298 DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
299 BOOL bOrder, HANDLE heap, DWORD flags)
303 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
304 ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags);
306 ret = ERROR_INVALID_PARAMETER;
310 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
311 if (ret == ERROR_INSUFFICIENT_BUFFER) {
312 *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize);
313 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
316 TRACE("returning %ld\n", ret);
321 /******************************************************************
322 * CreateIpForwardEntry (IPHLPAPI.@)
334 DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
336 TRACE("pRoute %p\n", pRoute);
337 /* could use SIOCADDRT, not sure I want to */
343 /******************************************************************
344 * CreateIpNetEntry (IPHLPAPI.@)
356 DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
358 TRACE("pArpEntry %p\n", pArpEntry);
359 /* could use SIOCSARP on systems that support it, not sure I want to */
365 /******************************************************************
366 * CreateProxyArpEntry (IPHLPAPI.@)
380 DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
382 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
385 /* marking Win2K+ functions not supported */
386 return ERROR_NOT_SUPPORTED;
390 /******************************************************************
391 * DeleteIPAddress (IPHLPAPI.@)
403 DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
405 TRACE("NTEContext %ld\n", NTEContext);
407 /* marking Win2K+ functions not supported */
408 return ERROR_NOT_SUPPORTED;
412 /******************************************************************
413 * DeleteIpForwardEntry (IPHLPAPI.@)
425 DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
427 TRACE("pRoute %p\n", pRoute);
428 /* could use SIOCDELRT, not sure I want to */
434 /******************************************************************
435 * DeleteIpNetEntry (IPHLPAPI.@)
447 DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
449 TRACE("pArpEntry %p\n", pArpEntry);
450 /* could use SIOCDARP on systems that support it, not sure I want to */
456 /******************************************************************
457 * DeleteProxyArpEntry (IPHLPAPI.@)
471 DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
473 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
476 /* marking Win2K+ functions not supported */
477 return ERROR_NOT_SUPPORTED;
481 /******************************************************************
482 * EnableRouter (IPHLPAPI.@)
488 * pOverlapped [In/Out]
495 DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped)
497 TRACE("pHandle %p, pOverlapped %p\n", pHandle, pOverlapped);
499 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
500 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
501 marking Win2K+ functions not supported */
502 return ERROR_NOT_SUPPORTED;
506 /******************************************************************
507 * FlushIpNetTable (IPHLPAPI.@)
519 DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex)
521 TRACE("dwIfIndex 0x%08lx\n", dwIfIndex);
523 /* this flushes the arp cache of the given index
524 marking Win2K+ functions not supported */
525 return ERROR_NOT_SUPPORTED;
529 /******************************************************************
530 * GetAdapterIndex (IPHLPAPI.@)
535 * AdapterName [In/Out]
543 DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
545 TRACE("AdapterName %p, IfIndex %p\n", AdapterName, IfIndex);
547 /* marking Win2K+ functions not supported */
548 return ERROR_NOT_SUPPORTED;
552 /******************************************************************
553 * GetAdaptersInfo (IPHLPAPI.@)
558 * pAdapterInfo [In/Out]
559 * pOutBufLen [In/Out]
566 DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
570 TRACE("pAdapterInfo %p, pOutBufLen %p\n", pAdapterInfo, pOutBufLen);
572 ret = ERROR_INVALID_PARAMETER;
574 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
576 if (numNonLoopbackInterfaces > 0) {
577 /* this calculation assumes only one address in the IP_ADDR_STRING lists.
578 that's okay, because:
579 - we don't get multiple addresses per adapter anyway
580 - we don't know about per-adapter gateways
581 - DHCP and WINS servers can have max one entry per list */
582 ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces;
584 if (!pAdapterInfo || *pOutBufLen < size) {
586 ret = ERROR_BUFFER_OVERFLOW;
589 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
592 size = sizeof(IP_ADAPTER_INFO) * table->numIndexes;
593 if (*pOutBufLen < size) {
595 ret = ERROR_INSUFFICIENT_BUFFER;
600 BOOL winsEnabled = FALSE;
601 IP_ADDRESS_STRING primaryWINS, secondaryWINS;
603 memset(pAdapterInfo, 0, size);
604 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
605 "\\Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ,
606 &hKey) == ERROR_SUCCESS) {
607 DWORD size = sizeof(primaryWINS.String);
610 RegQueryValueExA(hKey, "WinsServer", NULL, NULL,
611 primaryWINS.String, &size);
612 addr = inet_addr(primaryWINS.String);
613 if (addr != INADDR_NONE && addr != INADDR_ANY)
615 size = sizeof(secondaryWINS.String);
616 RegQueryValueExA(hKey, "BackupWinsServer", NULL, NULL,
617 secondaryWINS.String, &size);
618 addr = inet_addr(secondaryWINS.String);
619 if (addr != INADDR_NONE && addr != INADDR_ANY)
623 for (ndx = 0; ndx < table->numIndexes; ndx++) {
624 PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
625 DWORD addrLen = sizeof(ptr->Address), type;
627 /* on Win98 this is left empty, but whatever */
628 strncpy(ptr->AdapterName,
629 getInterfaceNameByIndex(table->indexes[ndx]),
630 sizeof(ptr->AdapterName));
631 ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0';
632 getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen,
633 ptr->Address, &type);
634 /* MS defines address length and type as UINT in some places and
635 DWORD in others, **sigh**. Don't want to assume that PUINT and
636 PDWORD are equiv (64-bit?) */
637 ptr->AddressLength = addrLen;
639 ptr->Index = table->indexes[ndx];
640 toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]),
641 ptr->IpAddressList.IpAddress.String);
642 toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]),
643 ptr->IpAddressList.IpMask.String);
645 ptr->HaveWins = TRUE;
646 memcpy(ptr->PrimaryWinsServer.IpAddress.String,
647 primaryWINS.String, sizeof(primaryWINS.String));
648 memcpy(ptr->SecondaryWinsServer.IpAddress.String,
649 secondaryWINS.String, sizeof(secondaryWINS.String));
651 if (ndx < table->numIndexes - 1)
652 ptr->Next = &pAdapterInfo[ndx + 1];
661 ret = ERROR_OUTOFMEMORY;
667 TRACE("returning %ld\n", ret);
672 /******************************************************************
673 * GetBestInterface (IPHLPAPI.@)
679 * pdwBestIfIndex [In/Out]
686 DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
690 TRACE("dwDestAddr 0x%08lx, pdwBestIfIndex %p\n", dwDestAddr, pdwBestIfIndex);
692 ret = ERROR_INVALID_PARAMETER;
694 MIB_IPFORWARDROW ipRow;
696 ret = GetBestRoute(dwDestAddr, 0, &ipRow);
697 if (ret == ERROR_SUCCESS)
698 *pdwBestIfIndex = ipRow.dwForwardIfIndex;
700 TRACE("returning %ld\n", ret);
705 /******************************************************************
706 * GetBestRoute (IPHLPAPI.@)
720 DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute)
722 PMIB_IPFORWARDTABLE table;
725 TRACE("dwDestAddr 0x%08lx, dwSourceAddr 0x%08lx, pBestRoute %p\n", dwDestAddr,
726 dwSourceAddr, pBestRoute);
728 return ERROR_INVALID_PARAMETER;
730 AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
732 DWORD ndx, matchedBits, matchedNdx = 0;
734 for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
735 if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
736 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
737 DWORD numShifts, mask;
739 for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
740 mask && !(mask & 1); mask >>= 1, numShifts++)
742 if (numShifts > matchedBits) {
743 matchedBits = numShifts;
748 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW));
749 HeapFree(GetProcessHeap(), 0, table);
753 ret = ERROR_OUTOFMEMORY;
754 TRACE("returning %ld\n", ret);
759 /******************************************************************
760 * GetFriendlyIfIndex (IPHLPAPI.@)
772 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
774 /* windows doesn't validate these, either, just makes sure the top byte is
775 cleared. I assume my ifenum module never gives an index with the top
777 TRACE("returning %ld\n", IfIndex);
782 /******************************************************************
783 * GetIcmpStatistics (IPHLPAPI.@)
795 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
799 TRACE("pStats %p\n", pStats);
800 ret = getICMPStats(pStats);
801 TRACE("returning %ld\n", ret);
806 /******************************************************************
807 * GetIfEntry (IPHLPAPI.@)
819 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
824 TRACE("pIfRow %p\n", pIfRow);
826 return ERROR_INVALID_PARAMETER;
828 name = getInterfaceNameByIndex(pIfRow->dwIndex);
830 ret = getInterfaceEntryByName(name, pIfRow);
832 ret = getInterfaceStatsByName(name, pIfRow);
835 ret = ERROR_INVALID_DATA;
836 TRACE("returning %ld\n", ret);
841 static int IfTableSorter(const void *a, const void *b)
846 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex;
853 /******************************************************************
854 * GetIfTable (IPHLPAPI.@)
868 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
872 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize,
875 ret = ERROR_INVALID_PARAMETER;
877 DWORD numInterfaces = getNumInterfaces();
878 ULONG size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW);
880 if (!pIfTable || *pdwSize < size) {
882 ret = ERROR_INSUFFICIENT_BUFFER;
885 InterfaceIndexTable *table = getInterfaceIndexTable();
888 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) *
890 if (*pdwSize < size) {
892 ret = ERROR_INSUFFICIENT_BUFFER;
897 pIfTable->dwNumEntries = 0;
898 for (ndx = 0; ndx < table->numIndexes; ndx++) {
899 pIfTable->table[ndx].dwIndex = table->indexes[ndx];
900 GetIfEntry(&pIfTable->table[ndx]);
901 pIfTable->dwNumEntries++;
904 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
911 ret = ERROR_OUTOFMEMORY;
914 TRACE("returning %ld\n", ret);
919 /******************************************************************
920 * GetInterfaceInfo (IPHLPAPI.@)
926 * dwOutBufLen [In/Out]
933 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
937 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen);
939 ret = ERROR_INVALID_PARAMETER;
941 DWORD numInterfaces = getNumInterfaces();
942 ULONG size = sizeof(IP_INTERFACE_INFO) + (numInterfaces - 1) *
943 sizeof(IP_ADAPTER_INDEX_MAP);
945 if (!pIfTable || *dwOutBufLen < size) {
947 ret = ERROR_INSUFFICIENT_BUFFER;
950 InterfaceIndexTable *table = getInterfaceIndexTable();
953 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes - 1) *
954 sizeof(IP_ADAPTER_INDEX_MAP);
955 if (*dwOutBufLen < size) {
957 ret = ERROR_INSUFFICIENT_BUFFER;
962 pIfTable->NumAdapters = 0;
963 for (ndx = 0; ndx < table->numIndexes; ndx++) {
964 const char *walker, *name;
967 pIfTable->Adapter[ndx].Index = table->indexes[ndx];
968 name = getInterfaceNameByIndex(table->indexes[ndx]);
969 for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
971 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
972 walker++, assigner++)
975 pIfTable->NumAdapters++;
982 ret = ERROR_OUTOFMEMORY;
985 TRACE("returning %ld\n", ret);
990 static int IpAddrTableSorter(const void *a, const void *b)
995 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr;
1002 /******************************************************************
1003 * GetIpAddrTable (IPHLPAPI.@)
1008 * pIpAddrTable [In/Out]
1017 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
1021 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize,
1024 ret = ERROR_INVALID_PARAMETER;
1026 DWORD numInterfaces = getNumInterfaces();
1027 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) *
1028 sizeof(MIB_IPADDRROW);
1030 if (!pIpAddrTable || *pdwSize < size) {
1032 ret = ERROR_INSUFFICIENT_BUFFER;
1035 InterfaceIndexTable *table = getInterfaceIndexTable();
1038 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) *
1039 sizeof(MIB_IPADDRROW);
1040 if (*pdwSize < size) {
1042 ret = ERROR_INSUFFICIENT_BUFFER;
1047 pIpAddrTable->dwNumEntries = 0;
1048 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1049 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx];
1050 pIpAddrTable->table[ndx].dwAddr =
1051 getInterfaceIPAddrByIndex(table->indexes[ndx]);
1052 pIpAddrTable->table[ndx].dwMask =
1053 getInterfaceMaskByIndex(table->indexes[ndx]);
1054 pIpAddrTable->table[ndx].dwBCastAddr =
1055 getInterfaceBCastAddrByIndex(table->indexes[ndx]);
1056 /* FIXME: hardcoded reasm size, not sure where to get it */
1057 pIpAddrTable->table[ndx].dwReasmSize = 65535;
1058 pIpAddrTable->table[ndx].unused1 = 0;
1059 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */
1060 pIpAddrTable->dwNumEntries++;
1063 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries,
1064 sizeof(MIB_IPADDRROW), IpAddrTableSorter);
1070 ret = ERROR_OUTOFMEMORY;
1073 TRACE("returning %ld\n", ret);
1078 static int IpForwardTableSorter(const void *a, const void *b)
1083 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b;
1085 ret = rowA->dwForwardDest - rowB->dwForwardDest;
1087 ret = rowA->dwForwardProto - rowB->dwForwardProto;
1089 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy;
1091 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop;
1101 /******************************************************************
1102 * GetIpForwardTable (IPHLPAPI.@)
1107 * pIpForwardTable [In/Out]
1116 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
1120 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable,
1121 pdwSize, (DWORD)bOrder);
1123 ret = ERROR_INVALID_PARAMETER;
1125 DWORD numRoutes = getNumRoutes();
1126 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) *
1127 sizeof(MIB_IPFORWARDROW);
1129 if (!pIpForwardTable || *pdwSize < sizeNeeded) {
1130 *pdwSize = sizeNeeded;
1131 ret = ERROR_INSUFFICIENT_BUFFER;
1134 RouteTable *table = getRouteTable();
1136 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) *
1137 sizeof(MIB_IPFORWARDROW);
1138 if (*pdwSize < sizeNeeded) {
1139 *pdwSize = sizeNeeded;
1140 ret = ERROR_INSUFFICIENT_BUFFER;
1145 pIpForwardTable->dwNumEntries = table->numRoutes;
1146 for (ndx = 0; ndx < numRoutes; ndx++) {
1147 pIpForwardTable->table[ndx].dwForwardIfIndex =
1148 table->routes[ndx].ifIndex;
1149 pIpForwardTable->table[ndx].dwForwardDest =
1150 table->routes[ndx].dest;
1151 pIpForwardTable->table[ndx].dwForwardMask =
1152 table->routes[ndx].mask;
1153 pIpForwardTable->table[ndx].dwForwardPolicy = 0;
1154 pIpForwardTable->table[ndx].dwForwardNextHop =
1155 table->routes[ndx].gateway;
1156 /* FIXME: this type is appropriate for local interfaces; may not
1157 always be appropriate */
1158 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
1159 /* FIXME: other protos might be appropriate, e.g. the default route
1160 is typically set with MIB_IPPROTO_NETMGMT instead */
1161 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL;
1162 /* punt on age and AS */
1163 pIpForwardTable->table[ndx].dwForwardAge = 0;
1164 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0;
1165 pIpForwardTable->table[ndx].dwForwardMetric1 =
1166 table->routes[ndx].metric;
1167 /* rest of the metrics are 0.. */
1168 pIpForwardTable->table[ndx].dwForwardMetric2 = 0;
1169 pIpForwardTable->table[ndx].dwForwardMetric3 = 0;
1170 pIpForwardTable->table[ndx].dwForwardMetric4 = 0;
1171 pIpForwardTable->table[ndx].dwForwardMetric5 = 0;
1174 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
1175 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
1181 ret = ERROR_OUTOFMEMORY;
1184 TRACE("returning %ld\n", ret);
1189 static int IpNetTableSorter(const void *a, const void *b)
1194 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr;
1201 /******************************************************************
1202 * GetIpNetTable (IPHLPAPI.@)
1207 * pIpNetTable [In/Out]
1216 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
1220 TRACE("pIpNetTable %p, pdwSize %p, bOrder %ld\n", pIpNetTable, pdwSize,
1223 ret = ERROR_INVALID_PARAMETER;
1225 DWORD numEntries = getNumArpEntries();
1226 ULONG size = sizeof(MIB_IPNETTABLE) + (numEntries - 1) *
1227 sizeof(MIB_IPNETROW);
1229 if (!pIpNetTable || *pdwSize < size) {
1231 ret = ERROR_INSUFFICIENT_BUFFER;
1234 PMIB_IPNETTABLE table = getArpTable();
1237 size = sizeof(MIB_IPNETTABLE) + (table->dwNumEntries - 1) *
1238 sizeof(MIB_IPNETROW);
1239 if (*pdwSize < size) {
1241 ret = ERROR_INSUFFICIENT_BUFFER;
1244 memcpy(pIpNetTable, table, size);
1246 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries,
1247 sizeof(MIB_IPNETROW), IpNetTableSorter);
1253 ret = ERROR_OUTOFMEMORY;
1256 TRACE("returning %ld\n", ret);
1261 /******************************************************************
1262 * GetIpStatistics (IPHLPAPI.@)
1274 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
1278 TRACE("pStats %p\n", pStats);
1279 ret = getIPStats(pStats);
1280 TRACE("returning %ld\n", ret);
1285 /******************************************************************
1286 * GetNetworkParams (IPHLPAPI.@)
1291 * pFixedInfo [In/Out]
1292 * pOutBufLen [In/Out]
1299 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
1305 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen);
1307 return ERROR_INVALID_PARAMETER;
1310 size = sizeof(FIXED_INFO) + (_res.nscount > 0 ? (_res.nscount - 1) *
1311 sizeof(IP_ADDR_STRING) : 0);
1312 if (!pFixedInfo || *pOutBufLen < size) {
1314 return ERROR_BUFFER_OVERFLOW;
1317 memset(pFixedInfo, 0, size);
1318 size = sizeof(pFixedInfo->HostName);
1319 GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
1320 size = sizeof(pFixedInfo->DomainName);
1321 GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
1322 if (_res.nscount > 0) {
1323 PIP_ADDR_STRING ptr;
1326 for (i = 0, ptr = &pFixedInfo->DnsServerList; i < _res.nscount && ptr;
1327 i++, ptr = ptr->Next) {
1328 toIPAddressString(_res.nsaddr_list[i].sin_addr.s_addr,
1329 ptr->IpAddress.String);
1330 if (i == _res.nscount - 1)
1333 ptr->Next = (PIP_ADDR_STRING)((LPBYTE)pFixedInfo + sizeof(FIXED_INFO));
1335 ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDR_STRING));
1338 pFixedInfo->NodeType = HYBRID_NODETYPE;
1339 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1340 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey);
1341 if (regReturn != ERROR_SUCCESS)
1342 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1343 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ,
1345 if (regReturn == ERROR_SUCCESS)
1347 DWORD size = sizeof(pFixedInfo->ScopeId);
1349 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, pFixedInfo->ScopeId, &size);
1353 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
1354 I suppose could also check for a listener on port 53 to set EnableDns */
1356 TRACE("returning %ld\n", ret);
1361 /******************************************************************
1362 * GetNumberOfInterfaces (IPHLPAPI.@)
1374 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
1378 TRACE("pdwNumIf %p\n", pdwNumIf);
1380 ret = ERROR_INVALID_PARAMETER;
1382 *pdwNumIf = getNumInterfaces();
1385 TRACE("returning %ld\n", ret);
1390 /******************************************************************
1391 * GetPerAdapterInfo (IPHLPAPI.@)
1397 * pPerAdapterInfo [In/Out]
1398 * pOutBufLen [In/Out]
1405 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
1407 TRACE("IfIndex %ld, pPerAdapterInfo %p, pOutBufLen %p\n", IfIndex,
1408 pPerAdapterInfo, pOutBufLen);
1410 /* marking Win2K+ functions not supported */
1411 return ERROR_NOT_SUPPORTED;
1415 /******************************************************************
1416 * GetRTTAndHopCount (IPHLPAPI.@)
1421 * DestIpAddress [In]
1431 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
1433 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
1434 DestIpAddress, HopCount, MaxHops, RTT);
1440 /******************************************************************
1441 * GetTcpStatistics (IPHLPAPI.@)
1453 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
1457 TRACE("pStats %p\n", pStats);
1458 ret = getTCPStats(pStats);
1459 TRACE("returning %ld\n", ret);
1464 static int TcpTableSorter(const void *a, const void *b)
1469 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
1471 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1473 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1475 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
1477 ret = rowA->dwRemotePort - rowB->dwRemotePort;
1487 /******************************************************************
1488 * GetTcpTable (IPHLPAPI.@)
1493 * pTcpTable [In/Out]
1502 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
1506 TRACE("pTcpTable %p, pdwSize %p, bOrder %ld\n", pTcpTable, pdwSize,
1509 ret = ERROR_INVALID_PARAMETER;
1511 DWORD numEntries = getNumTcpEntries();
1512 ULONG size = sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW);
1514 if (!pTcpTable || *pdwSize < size) {
1516 ret = ERROR_INSUFFICIENT_BUFFER;
1519 PMIB_TCPTABLE table = getTcpTable();
1522 size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) *
1524 if (*pdwSize < size) {
1526 ret = ERROR_INSUFFICIENT_BUFFER;
1529 memcpy(pTcpTable, table, size);
1531 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1532 sizeof(MIB_TCPROW), TcpTableSorter);
1538 ret = ERROR_OUTOFMEMORY;
1541 TRACE("returning %ld\n", ret);
1546 /******************************************************************
1547 * GetUdpStatistics (IPHLPAPI.@)
1559 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1563 TRACE("pStats %p\n", pStats);
1564 ret = getUDPStats(pStats);
1565 TRACE("returning %ld\n", ret);
1570 static int UdpTableSorter(const void *a, const void *b)
1575 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1577 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1579 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1587 /******************************************************************
1588 * GetUdpTable (IPHLPAPI.@)
1593 * pUdpTable [In/Out]
1602 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1606 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
1609 ret = ERROR_INVALID_PARAMETER;
1611 DWORD numEntries = getNumUdpEntries();
1612 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1614 if (!pUdpTable || *pdwSize < size) {
1616 ret = ERROR_INSUFFICIENT_BUFFER;
1619 PMIB_UDPTABLE table = getUdpTable();
1622 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1624 if (*pdwSize < size) {
1626 ret = ERROR_INSUFFICIENT_BUFFER;
1629 memcpy(pUdpTable, table, size);
1631 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1632 sizeof(MIB_UDPROW), UdpTableSorter);
1638 ret = ERROR_OUTOFMEMORY;
1641 TRACE("returning %ld\n", ret);
1646 /******************************************************************
1647 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1652 * pIPIfInfo [In/Out]
1653 * dwOutBufLen [In/Out]
1660 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1662 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
1663 /* a unidirectional adapter?? not bloody likely! */
1664 return ERROR_NOT_SUPPORTED;
1668 /******************************************************************
1669 * IpReleaseAddress (IPHLPAPI.@)
1674 * AdapterInfo [In/Out]
1681 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1683 TRACE("AdapterInfo %p\n", AdapterInfo);
1684 /* not a stub, never going to support this (and I never mark an adapter as
1685 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1686 return ERROR_NOT_SUPPORTED;
1690 /******************************************************************
1691 * IpRenewAddress (IPHLPAPI.@)
1696 * AdapterInfo [In/Out]
1703 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1705 TRACE("AdapterInfo %p\n", AdapterInfo);
1706 /* not a stub, never going to support this (and I never mark an adapter as
1707 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1708 return ERROR_NOT_SUPPORTED;
1712 /******************************************************************
1713 * NotifyAddrChange (IPHLPAPI.@)
1719 * overlapped [In/Out]
1726 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1728 TRACE("Handle %p, overlapped %p\n", Handle, overlapped);
1730 /* marking Win2K+ functions not supported */
1731 return ERROR_NOT_SUPPORTED;
1735 /******************************************************************
1736 * NotifyRouteChange (IPHLPAPI.@)
1742 * overlapped [In/Out]
1749 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1751 TRACE("Handle %p, overlapped %p\n", Handle, overlapped);
1753 /* marking Win2K+ functions not supported */
1754 return ERROR_NOT_SUPPORTED;
1758 /******************************************************************
1759 * SendARP (IPHLPAPI.@)
1767 * PhyAddrLen [In/Out]
1774 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
1776 TRACE("DestIP 0x%08lx, SrcIP 0x%08lx, pMacAddr %p, PhyAddrLen %p\n", DestIP,
1777 SrcIP, pMacAddr, PhyAddrLen);
1779 /* marking Win2K+ functions not supported */
1780 return ERROR_NOT_SUPPORTED;
1784 /******************************************************************
1785 * SetIfEntry (IPHLPAPI.@)
1797 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
1799 TRACE("pIfRow %p\n", pIfRow);
1800 /* this is supposed to set an administratively interface up or down.
1801 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
1802 this sort of down is indistinguishable from other sorts of down (e.g. no
1805 return ERROR_NOT_SUPPORTED;
1809 /******************************************************************
1810 * SetIpForwardEntry (IPHLPAPI.@)
1822 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
1824 TRACE("pRoute %p\n", pRoute);
1825 /* this is to add a route entry, how's it distinguishable from
1826 CreateIpForwardEntry?
1827 could use SIOCADDRT, not sure I want to */
1833 /******************************************************************
1834 * SetIpNetEntry (IPHLPAPI.@)
1839 * pArpEntry [In/Out]
1846 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
1848 TRACE("pArpEntry %p\n", pArpEntry);
1849 /* same as CreateIpNetEntry here, could use SIOCSARP, not sure I want to */
1855 /******************************************************************
1856 * SetIpStatistics (IPHLPAPI.@)
1868 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
1870 TRACE("pIpStats %p\n", pIpStats);
1876 /******************************************************************
1877 * SetIpTTL (IPHLPAPI.@)
1889 DWORD WINAPI SetIpTTL(UINT nTTL)
1891 TRACE("nTTL %d\n", nTTL);
1892 /* could echo nTTL > /proc/net/sys/net/ipv4/ip_default_ttl, not sure I
1893 want to. Could map EACCESS to ERROR_ACCESS_DENIED, I suppose */
1899 /******************************************************************
1900 * SetTcpEntry (IPHLPAPI.@)
1912 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
1914 TRACE("pTcpRow %p\n", pTcpRow);
1920 /******************************************************************
1921 * UnenableRouter (IPHLPAPI.@)
1926 * pOverlapped [In/Out]
1927 * lpdwEnableCount [In/Out]
1934 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
1936 TRACE("pOverlapped %p, lpdwEnableCount %p\n", pOverlapped, lpdwEnableCount);
1938 /* could echo "0" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
1939 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
1940 marking Win2K+ functions not supported */
1941 return ERROR_NOT_SUPPORTED;