Added an implementation of iphlpapi.dll; most Get* functions introduced through Win98 are included.
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c new file mode 100644 index 0000000..d2d054e --- /dev/null +++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -0,0 +1,1397 @@ +/* + * iphlpapi dll implementation + * + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include <stdlib.h> +#include <resolv.h> +#include "winbase.h" +#include "iphlpapi.h" +#include "ifenum.h" +#include "ipstats.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); + + +/****************************************************************** + * AddIPAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * Address [In] + * IpMask [In] + * IfIndex [In] + * NTEContext [In/Out] + * NTEInstance [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * CreateIpForwardEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pRoute [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute) +{ + /* could use SIOCADDRT, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * CreateIpNetEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pArpEntry [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry) +{ + /* could use SIOCSARP on systems that support it, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * CreateProxyArpEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * dwAddress [In] + * dwMask [In] + * dwIfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * DeleteIPAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * NTEContext [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteIPAddress(ULONG NTEContext) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * DeleteIpForwardEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pRoute [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute) +{ + /* could use SIOCDELRT, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * DeleteIpNetEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pArpEntry [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry) +{ + /* could use SIOCDARP on systems that support it, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * DeleteProxyArpEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * dwAddress [In] + * dwMask [In] + * dwIfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * EnableRouter (IPHLPAPI.@) + * + * + * PARAMS + * + * pHandle [In/Out] + * pOverlapped [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped) +{ + FIXME(":stub\n"); + /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to + could map EACCESS to ERROR_ACCESS_DENIED, I suppose + marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * FlushIpNetTable (IPHLPAPI.@) + * + * + * PARAMS + * + * dwIfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex) +{ + FIXME(":stub\n"); + /* this flushes the arp cache of the given index + marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * GetAdapterIndex (IPHLPAPI.@) + * + * + * PARAMS + * + * AdapterName [In/Out] + * IfIndex [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * GetAdaptersInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * pAdapterInfo [In/Out] + * pOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) +{ + DWORD ret; + + if (!pOutBufLen) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces(); + + if (numNonLoopbackInterfaces > 0) { + /* this calculation assumes only one address in the IP_ADDR_STRING lists. + that's okay, because: + - we don't get multiple addresses per adapter anyway + - we don't know about per-adapter gateways + - we don't know about DHCP or WINS (and these must be single anyway) */ + ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces; + + if (!pAdapterInfo || *pOutBufLen < size) { + *pOutBufLen = size; + ret = ERROR_BUFFER_OVERFLOW; + } + else { + InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable(); + + if (table) { + size = sizeof(IP_ADAPTER_INFO) * table->numIndexes; + if (*pOutBufLen < size) { + *pOutBufLen = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + memset(pAdapterInfo, 0, size); + for (ndx = 0; ndx < table->numIndexes; ndx++) { + PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx]; + DWORD addrLen = sizeof(ptr->Address), type; + + /* on Win98 this is left empty, but whatever */ + strncpy(ptr->AdapterName, + getInterfaceNameByIndex(table->indexes[ndx]), + sizeof(ptr->AdapterName)); + ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0'; + getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen, + ptr->Address, &type); + /* MS defines address length and type as UINT in some places and + DWORD in others, **sigh**. Don't want to assume that PUINT and + PDWORD are equiv (64-bit?) */ + ptr->AddressLength = addrLen; + ptr->Type = type; + ptr->Index = table->indexes[ndx]; + toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]), + ptr->IpAddressList.IpAddress.String); + toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]), + ptr->IpAddressList.IpMask.String); + if (ndx < table->numIndexes + 1) + ptr->Next = &pAdapterInfo[ndx + 1]; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + else + ret = ERROR_NO_DATA; + } + return ret; +} + + +/****************************************************************** + * GetBestInterface (IPHLPAPI.@) + * + * + * PARAMS + * + * dwDestAddr [In] + * pdwBestIfIndex [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * GetBestRoute (IPHLPAPI.@) + * + * + * PARAMS + * + * dwDestAddr [In] + * dwSourceAddr [In] + * OUT [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * GetFriendlyIfIndex (IPHLPAPI.@) + * + * + * PARAMS + * + * IfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex) +{ + /* windows doesn't validate these, either, just makes sure the top byte is + cleared. I assume my ipshared module never gives an index with the top + byte set. */ + return IfIndex; +} + + +/****************************************************************** + * GetIcmpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats) +{ + return getICMPStats(pStats); +} + + +/****************************************************************** + * GetIfEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfRow [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow) +{ + DWORD ret; + const char *name; + + if (!pIfRow) + return ERROR_INVALID_PARAMETER; + + name = getInterfaceNameByIndex(pIfRow->dwIndex); + if (name) { + ret = getInterfaceEntryByName(name, pIfRow); + if (ret == NO_ERROR) + ret = getInterfaceStatsByName(name, pIfRow); + } + else + ret = ERROR_INVALID_DATA; + return ret; +} + + +/****************************************************************** + * GetIfTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numInterfaces = getNumInterfaces(); + ULONG size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW); + + if (!pIfTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + InterfaceIndexTable *table = getInterfaceIndexTable(); + + if (table) { + size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) * + sizeof(MIB_IFROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + if (bOrder) + FIXME(":order not implemented"); + pIfTable->dwNumEntries = 0; + for (ndx = 0; ndx < table->numIndexes; ndx++) { + pIfTable->table[ndx].dwIndex = table->indexes[ndx]; + GetIfEntry(&pIfTable->table[ndx]); + pIfTable->dwNumEntries++; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetInterfaceInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfTable [In/Out] + * dwOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen) +{ + DWORD ret; + + if (!dwOutBufLen) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numInterfaces = getNumInterfaces(); + ULONG size = sizeof(IP_INTERFACE_INFO) + (numInterfaces - 1) * + sizeof(IP_ADAPTER_INDEX_MAP); + + if (!pIfTable || *dwOutBufLen < size) { + *dwOutBufLen = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + InterfaceIndexTable *table = getInterfaceIndexTable(); + + if (table) { + size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes - 1) * + sizeof(IP_ADAPTER_INDEX_MAP); + if (*dwOutBufLen < size) { + *dwOutBufLen = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + pIfTable->NumAdapters = 0; + for (ndx = 0; ndx < table->numIndexes; ndx++) { + const char *walker, *name; + WCHAR *assigner; + + pIfTable->Adapter[ndx].Index = table->indexes[ndx]; + name = getInterfaceNameByIndex(table->indexes[ndx]); + for (walker = name, assigner = pIfTable->Adapter[ndx].Name; + walker && *walker && + assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1; + walker++, assigner++) + *assigner = *walker; + *assigner = 0; + pIfTable->NumAdapters++; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpAddrTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpAddrTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numInterfaces = getNumInterfaces(); + ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) * + sizeof(MIB_IPADDRROW); + + if (!pIpAddrTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + InterfaceIndexTable *table = getInterfaceIndexTable(); + + if (table) { + size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) * + sizeof(MIB_IPADDRROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + if (bOrder) + FIXME(":order not implemented"); + pIpAddrTable->dwNumEntries = 0; + for (ndx = 0; ndx < table->numIndexes; ndx++) { + pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx]; + pIpAddrTable->table[ndx].dwAddr = + getInterfaceIPAddrByIndex(table->indexes[ndx]); + pIpAddrTable->table[ndx].dwMask = + getInterfaceMaskByIndex(table->indexes[ndx]); + pIpAddrTable->table[ndx].dwBCastAddr = + getInterfaceBCastAddrByIndex(table->indexes[ndx]); + /* FIXME: hardcoded reasm size, not sure where to get it */ + pIpAddrTable->table[ndx].dwReasmSize = 65535; + pIpAddrTable->table[ndx].unused1 = 0; + pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */ + pIpAddrTable->dwNumEntries++; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpForwardTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpForwardTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numRoutes = getNumRoutes(); + ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * + sizeof(MIB_IPFORWARDROW); + + if (!pIpForwardTable || *pdwSize < sizeNeeded) { + *pdwSize = sizeNeeded; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + RouteTable *table = getRouteTable(); + if (table) { + sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) * + sizeof(MIB_IPFORWARDROW); + if (*pdwSize < sizeNeeded) { + *pdwSize = sizeNeeded; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + if (bOrder) + FIXME(":order not implemented"); + pIpForwardTable->dwNumEntries = table->numRoutes; + for (ndx = 0; ndx < numRoutes; ndx++) { + pIpForwardTable->table[ndx].dwForwardIfIndex = + table->routes[ndx].ifIndex; + pIpForwardTable->table[ndx].dwForwardDest = + table->routes[ndx].dest; + pIpForwardTable->table[ndx].dwForwardMask = + table->routes[ndx].mask; + pIpForwardTable->table[ndx].dwForwardPolicy = 0; + pIpForwardTable->table[ndx].dwForwardNextHop = + table->routes[ndx].gateway; + /* FIXME: this type is appropriate for local interfaces; may not + always be appropriate */ + pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT; + /* FIXME: other protos might be appropriate, e.g. the default route + is typically set with MIB_IPPROTO_NETMGMT instead */ + pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL; + /* punt on age and AS */ + pIpForwardTable->table[ndx].dwForwardAge = 0; + pIpForwardTable->table[ndx].dwForwardNextHopAS = 0; + pIpForwardTable->table[ndx].dwForwardMetric1 = + table->routes[ndx].metric; + /* rest of the metrics are 0.. */ + pIpForwardTable->table[ndx].dwForwardMetric2 = 0; + pIpForwardTable->table[ndx].dwForwardMetric3 = 0; + pIpForwardTable->table[ndx].dwForwardMetric4 = 0; + pIpForwardTable->table[ndx].dwForwardMetric5 = 0; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpNetTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpNetTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numEntries = getNumArpEntries(); + ULONG size = sizeof(MIB_IPNETTABLE) + (numEntries - 1) * + sizeof(MIB_IPNETROW); + + if (!pIpNetTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + PMIB_IPNETTABLE table = getArpTable(); + + if (table) { + size = sizeof(MIB_IPNETTABLE) + (table->dwNumEntries - 1) * + sizeof(MIB_IPNETROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + if (bOrder) + FIXME(":order not implemented"); + memcpy(pIpNetTable, table, size); + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats) +{ + return getIPStats(pStats); +} + + +/****************************************************************** + * GetNetworkParams (IPHLPAPI.@) + * + * + * PARAMS + * + * pFixedInfo [In/Out] + * pOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) +{ + DWORD size; + + if (!pOutBufLen) + return ERROR_INVALID_PARAMETER; + + size = sizeof(FIXED_INFO) + min(1, (_res.nscount - 1) * + sizeof(IP_ADDR_STRING)); + if (!pFixedInfo || *pOutBufLen < size) { + *pOutBufLen = size; + return ERROR_BUFFER_OVERFLOW; + } + + memset(pFixedInfo, 0, size); + size = sizeof(pFixedInfo->HostName); + GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size); + size = sizeof(pFixedInfo->DomainName); + GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size); + if (_res.nscount > 0) { + PIP_ADDR_STRING ptr; + int i; + + for (i = 0, ptr = &pFixedInfo->DnsServerList; i < _res.nscount; + i++, ptr = ptr->Next) { + toIPAddressString(_res.nsaddr_list[i].sin_addr.s_addr, + ptr->IpAddress.String); + ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDRESS_STRING)); + } + } + /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward + I suppose could also check for a listener on port 53 to set EnableDns */ + return NO_ERROR; +} + + +/****************************************************************** + * GetNumberOfInterfaces (IPHLPAPI.@) + * + * + * PARAMS + * + * pdwNumIf [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf) +{ + DWORD ret; + + if (!pdwNumIf) + ret = ERROR_INVALID_PARAMETER; + else { + *pdwNumIf = getNumInterfaces(); + ret = NO_ERROR; + } + return ret; +} + + +/****************************************************************** + * GetPerAdapterInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * IfIndex [In] + * pPerAdapterInfo [In/Out] + * pOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * GetRTTAndHopCount (IPHLPAPI.@) + * + * + * PARAMS + * + * DestIpAddress [In] + * HopCount [In/Out] + * MaxHops [In] + * RTT [In/Out] + * + * RETURNS + * + * BOOL + * + */ +BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT) +{ + FIXME(":stub\n"); + return (BOOL) 0; +} + + +/****************************************************************** + * GetTcpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats) +{ + return getTCPStats(pStats); +} + + +/****************************************************************** + * GetTcpTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pTcpTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numEntries = getNumTcpEntries(); + ULONG size = sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW); + + if (!pTcpTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + PMIB_TCPTABLE table = getTcpTable(); + + if (table) { + size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) * + sizeof(MIB_TCPROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + if (bOrder) + FIXME(":order not implemented"); + memcpy(pTcpTable, table, size); + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetUdpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats) +{ + return getUDPStats(pStats); +} + + +/****************************************************************** + * GetUdpTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pUdpTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numEntries = getNumUdpEntries(); + ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW); + + if (!pUdpTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + PMIB_UDPTABLE table = getUdpTable(); + + if (table) { + size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) * + sizeof(MIB_UDPROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + if (bOrder) + FIXME(":order not implemented"); + memcpy(pUdpTable, table, size); + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetUniDirectionalAdapterInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * pIPIfInfo [In/Out] + * dwOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen) +{ + /* a unidirectional adapter?? not bloody likely! */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * IpReleaseAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * AdapterInfo [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) +{ + /* not a stub, never going to support this (and I never mark an adapter as + DHCP enabled, see GetAdaptersInfo, so this should never get called) */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * IpRenewAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * AdapterInfo [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) +{ + /* not a stub, never going to support this (and I never mark an adapter as + DHCP enabled, see GetAdaptersInfo, so this should never get called) */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * NotifyAddrChange (IPHLPAPI.@) + * + * + * PARAMS + * + * Handle [In/Out] + * overlapped [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * NotifyRouteChange (IPHLPAPI.@) + * + * + * PARAMS + * + * Handle [In/Out] + * overlapped [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * SendARP (IPHLPAPI.@) + * + * + * PARAMS + * + * DestIP [In] + * SrcIP [In] + * pMacAddr [In/Out] + * PhyAddrLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * SetIfEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfRow [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow) +{ + /* this is supposed to set an administratively interface up or down. + Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and + this sort of down is indistinguishable from other sorts of down (e.g. no + link). */ + FIXME(":stub\n"); + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * SetIpForwardEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pRoute [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute) +{ + /* this is to add a route entry, how's it distinguishable from + CreateIpForwardEntry? + could use SIOCADDRT, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetIpNetEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pArpEntry [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry) +{ + /* same as CreateIpNetEntry here, could use SIOCSARP, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetIpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetIpTTL (IPHLPAPI.@) + * + * + * PARAMS + * + * nTTL [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpTTL(UINT nTTL) +{ + /* could echo nTTL > /proc/net/sys/net/ipv4/ip_default_ttl, not sure I + want to. Could map EACCESS to ERROR_ACCESS_DENIED, I suppose */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetTcpEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pTcpRow [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * UnenableRouter (IPHLPAPI.@) + * + * + * PARAMS + * + * pOverlapped [In/Out] + * lpdwEnableCount [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount) +{ + FIXME(":stub\n"); + /* could echo "0" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to + could map EACCESS to ERROR_ACCESS_DENIED, I suppose + marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +}