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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "iphlpapi_private.h"
26 #include <sys/types.h>
27 #ifdef HAVE_NETINET_IN_H
28 # include <netinet/in.h>
30 #ifdef HAVE_ARPA_INET_H
31 # include <arpa/inet.h>
33 #ifdef HAVE_ARPA_NAMESER_H
34 # include <arpa/nameser.h>
50 #include "wine/debug.h"
52 #include "dhcp/rosdhcp_public.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi
);
56 typedef struct _NAME_SERVER_LIST_CONTEXT
{
59 PIP_PER_ADAPTER_INFO pData
;
61 IP_ADDR_STRING
*pLastAddr
;
62 } NAME_SERVER_LIST_CONTEXT
, *PNAME_SERVER_LIST_CONTEXT
;
64 BOOL WINAPI
DllMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
67 case DLL_PROCESS_ATTACH
:
68 DisableThreadLibraryCalls( hinstDLL
);
72 case DLL_PROCESS_DETACH
:
79 /******************************************************************
80 * AddIPAddress (IPHLPAPI.@)
89 * NTEInstance [In/Out]
96 DWORD WINAPI
AddIPAddress(IPAddr Address
, IPMask Netmask
, DWORD IfIndex
, PULONG NteContext
, PULONG NteInstance
)
98 return RtlNtStatusToDosError(addIPAddress(Address
, Netmask
, IfIndex
, NteContext
, NteInstance
));
101 DWORD
getInterfaceGatewayByIndex(DWORD index
)
103 DWORD ndx
, retVal
= 0, numRoutes
= getNumRoutes();
104 RouteTable
*table
= getRouteTable();
105 if (!table
) return 0;
107 for (ndx
= 0; ndx
< numRoutes
; ndx
++)
109 if ((table
->routes
[ndx
].ifIndex
== (index
)) && (table
->routes
[ndx
].dest
== 0))
110 retVal
= table
->routes
[ndx
].gateway
;
112 HeapFree(GetProcessHeap(), 0, table
);
116 /******************************************************************
117 * AllocateAndGetIfTableFromStack (IPHLPAPI.@)
122 * ppIfTable [Out] -- pointer into which the MIB_IFTABLE is
123 * allocated and returned.
124 * bOrder [In] -- passed to GetIfTable to order the table
125 * heap [In] -- heap from which the table is allocated
126 * flags [In] -- flags to HeapAlloc
128 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
129 * GetIfTable returns otherwise
132 DWORD WINAPI
AllocateAndGetIfTableFromStack(PMIB_IFTABLE
*ppIfTable
,
133 BOOL bOrder
, HANDLE heap
, DWORD flags
)
137 TRACE("ppIfTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n", ppIfTable
,
138 (DWORD
)bOrder
, (DWORD
)heap
, flags
);
140 ret
= ERROR_INVALID_PARAMETER
;
144 ret
= GetIfTable(*ppIfTable
, &dwSize
, bOrder
);
145 if (ret
== ERROR_INSUFFICIENT_BUFFER
) {
146 *ppIfTable
= (PMIB_IFTABLE
)HeapAlloc(heap
, flags
, dwSize
);
147 ret
= GetIfTable(*ppIfTable
, &dwSize
, bOrder
);
150 TRACE("returning %ld\n", ret
);
155 /******************************************************************
156 * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@)
161 * ppIpAddrTable [Out]
162 * bOrder [In] -- passed to GetIpAddrTable to order the table
163 * heap [In] -- heap from which the table is allocated
164 * flags [In] -- flags to HeapAlloc
171 DWORD WINAPI
AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE
*ppIpAddrTable
,
172 BOOL bOrder
, HANDLE heap
, DWORD flags
)
176 TRACE("ppIpAddrTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
177 ppIpAddrTable
, (DWORD
)bOrder
, (DWORD
)heap
, flags
);
179 ret
= ERROR_INVALID_PARAMETER
;
183 ret
= GetIpAddrTable(*ppIpAddrTable
, &dwSize
, bOrder
);
184 if (ret
== ERROR_INSUFFICIENT_BUFFER
) {
185 *ppIpAddrTable
= (PMIB_IPADDRTABLE
)HeapAlloc(heap
, flags
, dwSize
);
186 ret
= GetIpAddrTable(*ppIpAddrTable
, &dwSize
, bOrder
);
189 TRACE("returning %ld\n", ret
);
194 /******************************************************************
195 * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
198 * ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is
199 * allocated and returned.
200 * bOrder [In] -- passed to GetIfTable to order the table
201 * heap [In] -- heap from which the table is allocated
202 * flags [In] -- flags to HeapAlloc
204 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
205 * GetIpForwardTable returns otherwise
208 DWORD WINAPI
AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE
*
209 ppIpForwardTable
, BOOL bOrder
, HANDLE heap
, DWORD flags
)
213 TRACE("ppIpForwardTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
214 ppIpForwardTable
, (DWORD
)bOrder
, (DWORD
)heap
, flags
);
215 if (!ppIpForwardTable
)
216 ret
= ERROR_INVALID_PARAMETER
;
220 ret
= GetIpForwardTable(*ppIpForwardTable
, &dwSize
, bOrder
);
221 if (ret
== ERROR_INSUFFICIENT_BUFFER
) {
222 *ppIpForwardTable
= (PMIB_IPFORWARDTABLE
)HeapAlloc(heap
, flags
, dwSize
);
223 ret
= GetIpForwardTable(*ppIpForwardTable
, &dwSize
, bOrder
);
226 TRACE("returning %ld\n", ret
);
231 /******************************************************************
232 * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@)
238 * bOrder [In] -- passed to GetIpNetTable to order the table
239 * heap [In] -- heap from which the table is allocated
240 * flags [In] -- flags to HeapAlloc
247 DWORD WINAPI
AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE
*ppIpNetTable
,
248 BOOL bOrder
, HANDLE heap
, DWORD flags
)
252 TRACE("ppIpNetTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
253 ppIpNetTable
, (DWORD
)bOrder
, (DWORD
)heap
, flags
);
255 ret
= ERROR_INVALID_PARAMETER
;
259 ret
= GetIpNetTable(*ppIpNetTable
, &dwSize
, bOrder
);
260 if (ret
== ERROR_INSUFFICIENT_BUFFER
) {
261 *ppIpNetTable
= (PMIB_IPNETTABLE
)HeapAlloc(heap
, flags
, dwSize
);
262 ret
= GetIpNetTable(*ppIpNetTable
, &dwSize
, bOrder
);
265 TRACE("returning %ld\n", ret
);
270 /******************************************************************
271 * AllocateAndGetTcpTableFromStack (IPHLPAPI.@)
277 * bOrder [In] -- passed to GetTcpTable to order the table
278 * heap [In] -- heap from which the table is allocated
279 * flags [In] -- flags to HeapAlloc
286 DWORD WINAPI
AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE
*ppTcpTable
,
287 BOOL bOrder
, HANDLE heap
, DWORD flags
)
291 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
292 ppTcpTable
, (DWORD
)bOrder
, (DWORD
)heap
, flags
);
294 ret
= ERROR_INVALID_PARAMETER
;
298 ret
= GetTcpTable(*ppTcpTable
, &dwSize
, bOrder
);
299 if (ret
== ERROR_INSUFFICIENT_BUFFER
) {
300 *ppTcpTable
= (PMIB_TCPTABLE
)HeapAlloc(heap
, flags
, dwSize
);
301 ret
= GetTcpTable(*ppTcpTable
, &dwSize
, bOrder
);
304 TRACE("returning %ld\n", ret
);
309 /******************************************************************
310 * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
316 * bOrder [In] -- passed to GetUdpTable to order the table
317 * heap [In] -- heap from which the table is allocated
318 * flags [In] -- flags to HeapAlloc
325 DWORD WINAPI
AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE
*ppUdpTable
,
326 BOOL bOrder
, HANDLE heap
, DWORD flags
)
330 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
331 ppUdpTable
, (DWORD
)bOrder
, (DWORD
)heap
, flags
);
333 ret
= ERROR_INVALID_PARAMETER
;
337 ret
= GetUdpTable(*ppUdpTable
, &dwSize
, bOrder
);
338 if (ret
== ERROR_INSUFFICIENT_BUFFER
) {
339 *ppUdpTable
= (PMIB_UDPTABLE
)HeapAlloc(heap
, flags
, dwSize
);
340 ret
= GetUdpTable(*ppUdpTable
, &dwSize
, bOrder
);
343 TRACE("returning %ld\n", ret
);
348 /******************************************************************
349 * CreateIpForwardEntry (IPHLPAPI.@)
361 DWORD WINAPI
CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute
)
363 return createIpForwardEntry( pRoute
);
367 /******************************************************************
368 * CreateIpNetEntry (IPHLPAPI.@)
380 DWORD WINAPI
CreateIpNetEntry(PMIB_IPNETROW pArpEntry
)
382 TRACE("pArpEntry %p\n", pArpEntry
);
383 /* could use SIOCSARP on systems that support it, not sure I want to */
389 /******************************************************************
390 * CreateProxyArpEntry (IPHLPAPI.@)
404 DWORD WINAPI
CreateProxyArpEntry(DWORD dwAddress
, DWORD dwMask
, DWORD dwIfIndex
)
406 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress
,
409 /* marking Win2K+ functions not supported */
410 return ERROR_NOT_SUPPORTED
;
414 /******************************************************************
415 * DeleteIPAddress (IPHLPAPI.@)
427 DWORD WINAPI
DeleteIPAddress(ULONG NTEContext
)
429 TRACE("NTEContext %ld\n", NTEContext
);
430 return RtlNtStatusToDosError(deleteIpAddress(NTEContext
));
434 /******************************************************************
435 * DeleteIpForwardEntry (IPHLPAPI.@)
447 DWORD WINAPI
DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute
)
449 return deleteIpForwardEntry( pRoute
);
453 /******************************************************************
454 * DeleteIpNetEntry (IPHLPAPI.@)
466 DWORD WINAPI
DeleteIpNetEntry(PMIB_IPNETROW pArpEntry
)
468 TRACE("pArpEntry %p\n", pArpEntry
);
469 /* could use SIOCDARP on systems that support it, not sure I want to */
475 /******************************************************************
476 * DeleteProxyArpEntry (IPHLPAPI.@)
490 DWORD WINAPI
DeleteProxyArpEntry(DWORD dwAddress
, DWORD dwMask
, DWORD dwIfIndex
)
492 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress
,
495 /* marking Win2K+ functions not supported */
496 return ERROR_NOT_SUPPORTED
;
499 /******************************************************************
500 * EnableRouter (IPHLPAPI.@)
506 * pOverlapped [In/Out]
513 DWORD WINAPI
EnableRouter(HANDLE
* pHandle
, OVERLAPPED
* pOverlapped
)
515 TRACE("pHandle %p, pOverlapped %p\n", pHandle
, pOverlapped
);
517 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
518 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
519 marking Win2K+ functions not supported */
520 return ERROR_NOT_SUPPORTED
;
524 /******************************************************************
525 * FlushIpNetTable (IPHLPAPI.@)
537 DWORD WINAPI
FlushIpNetTable(DWORD dwIfIndex
)
539 TRACE("dwIfIndex 0x%08lx\n", dwIfIndex
);
541 /* this flushes the arp cache of the given index
542 marking Win2K+ functions not supported */
543 return ERROR_NOT_SUPPORTED
;
547 /******************************************************************
548 * GetAdapterIndex (IPHLPAPI.@)
553 * AdapterName [In/Out]
561 DWORD WINAPI
GetAdapterIndex(LPWSTR AdapterName
, PULONG IfIndex
)
563 TRACE("AdapterName %p, IfIndex %p\n", AdapterName
, IfIndex
);
565 /* marking Win2K+ functions not supported */
566 return ERROR_NOT_SUPPORTED
;
570 /******************************************************************
571 * GetAdaptersInfo (IPHLPAPI.@)
576 * pAdapterInfo [In/Out]
577 * pOutBufLen [In/Out]
584 DWORD WINAPI
GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
590 TRACE("pAdapterInfo %p, pOutBufLen %p\n", pAdapterInfo
, pOutBufLen
);
592 ret
= ERROR_INVALID_PARAMETER
;
594 DWORD numNonLoopbackInterfaces
= getNumNonLoopbackInterfaces();
596 if (numNonLoopbackInterfaces
> 0) {
597 /* this calculation assumes only one address in the IP_ADDR_STRING lists.
598 that's okay, because:
599 - we don't get multiple addresses per adapter anyway
600 - we don't know about per-adapter gateways
601 - DHCP and WINS servers can have max one entry per list */
602 ULONG size
= sizeof(IP_ADAPTER_INFO
) * numNonLoopbackInterfaces
;
604 if (!pAdapterInfo
|| *pOutBufLen
< size
) {
606 ret
= ERROR_BUFFER_OVERFLOW
;
609 InterfaceIndexTable
*table
= getNonLoopbackInterfaceIndexTable();
612 size
= sizeof(IP_ADAPTER_INFO
) * table
->numIndexes
;
613 if (*pOutBufLen
< size
) {
615 ret
= ERROR_INSUFFICIENT_BUFFER
;
620 BOOL winsEnabled
= FALSE
;
621 IP_ADDRESS_STRING primaryWINS
, secondaryWINS
;
623 memset(pAdapterInfo
, 0, size
);
624 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
625 "Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ
,
626 &hKey
) == ERROR_SUCCESS
) {
627 DWORD size
= sizeof(primaryWINS
.String
);
630 RegQueryValueExA(hKey
, "WinsServer", NULL
, NULL
,
631 (PBYTE
)primaryWINS
.String
, &size
);
632 addr
= inet_addr(primaryWINS
.String
);
633 if (addr
!= INADDR_NONE
&& addr
!= INADDR_ANY
)
635 size
= sizeof(secondaryWINS
.String
);
636 RegQueryValueExA(hKey
, "BackupWinsServer", NULL
, NULL
,
637 (PBYTE
)secondaryWINS
.String
, &size
);
638 addr
= inet_addr(secondaryWINS
.String
);
639 if (addr
!= INADDR_NONE
&& addr
!= INADDR_ANY
)
643 TRACE("num of index is %lu\n", table
->numIndexes
);
644 for (ndx
= 0; ndx
< table
->numIndexes
; ndx
++) {
645 PIP_ADAPTER_INFO ptr
= &pAdapterInfo
[ndx
];
646 DWORD addrLen
= sizeof(ptr
->Address
), type
;
648 getInterfaceNameByIndex(table
->indexes
[ndx
]);
650 ret
= ERROR_OUTOFMEMORY
;
654 /* on Win98 this is left empty, but whatever */
655 strncpy(ptr
->AdapterName
,ifname
,sizeof(ptr
->AdapterName
));
656 consumeInterfaceName(ifname
);
657 ptr
->AdapterName
[MAX_ADAPTER_NAME_LENGTH
] = '\0';
658 getInterfacePhysicalByIndex(table
->indexes
[ndx
], &addrLen
,
659 ptr
->Address
, &type
);
660 /* MS defines address length and type as UINT in some places and
661 DWORD in others, **sigh**. Don't want to assume that PUINT and
662 PDWORD are equiv (64-bit?) */
663 ptr
->AddressLength
= addrLen
;
665 ptr
->Index
= table
->indexes
[ndx
];
666 toIPAddressString(getInterfaceIPAddrByIndex(table
->indexes
[ndx
]),
667 ptr
->IpAddressList
.IpAddress
.String
);
668 toIPAddressString(getInterfaceMaskByIndex(table
->indexes
[ndx
]),
669 ptr
->IpAddressList
.IpMask
.String
);
670 toIPAddressString(getInterfaceGatewayByIndex(table
->indexes
[ndx
]),
671 ptr
->GatewayList
.IpAddress
.String
);
672 getDhcpInfoForAdapter(table
->indexes
[ndx
], &dhcpEnabled
,
673 &dhcpServer
, &ptr
->LeaseObtained
,
675 ptr
->DhcpEnabled
= (DWORD
) dhcpEnabled
;
676 toIPAddressString(dhcpServer
,
677 ptr
->DhcpServer
.IpAddress
.String
);
679 ptr
->HaveWins
= TRUE
;
680 memcpy(ptr
->PrimaryWinsServer
.IpAddress
.String
,
681 primaryWINS
.String
, sizeof(primaryWINS
.String
));
682 memcpy(ptr
->SecondaryWinsServer
.IpAddress
.String
,
683 secondaryWINS
.String
, sizeof(secondaryWINS
.String
));
685 if (ndx
< table
->numIndexes
- 1)
686 ptr
->Next
= &pAdapterInfo
[ndx
+ 1];
695 ret
= ERROR_OUTOFMEMORY
;
701 TRACE("returning %ld\n", ret
);
706 /******************************************************************
707 * GetBestInterface (IPHLPAPI.@)
713 * pdwBestIfIndex [In/Out]
720 DWORD WINAPI
GetBestInterface(IPAddr dwDestAddr
, PDWORD pdwBestIfIndex
)
724 TRACE("dwDestAddr 0x%08lx, pdwBestIfIndex %p\n", dwDestAddr
, pdwBestIfIndex
);
726 ret
= ERROR_INVALID_PARAMETER
;
728 MIB_IPFORWARDROW ipRow
;
730 ret
= GetBestRoute(dwDestAddr
, 0, &ipRow
);
731 if (ret
== ERROR_SUCCESS
)
732 *pdwBestIfIndex
= ipRow
.dwForwardIfIndex
;
734 TRACE("returning %ld\n", ret
);
739 /******************************************************************
740 * GetBestRoute (IPHLPAPI.@)
754 DWORD WINAPI
GetBestRoute(DWORD dwDestAddr
, DWORD dwSourceAddr
, PMIB_IPFORWARDROW pBestRoute
)
756 PMIB_IPFORWARDTABLE table
;
759 TRACE("dwDestAddr 0x%08lx, dwSourceAddr 0x%08lx, pBestRoute %p\n", dwDestAddr
,
760 dwSourceAddr
, pBestRoute
);
762 return ERROR_INVALID_PARAMETER
;
764 AllocateAndGetIpForwardTableFromStack(&table
, FALSE
, GetProcessHeap(), 0);
766 DWORD ndx
, matchedBits
, matchedNdx
= 0;
768 for (ndx
= 0, matchedBits
= 0; ndx
< table
->dwNumEntries
; ndx
++) {
769 if ((dwDestAddr
& table
->table
[ndx
].dwForwardMask
) ==
770 (table
->table
[ndx
].dwForwardDest
& table
->table
[ndx
].dwForwardMask
)) {
771 DWORD numShifts
, mask
;
773 for (numShifts
= 0, mask
= table
->table
[ndx
].dwForwardMask
;
774 mask
&& !(mask
& 1); mask
>>= 1, numShifts
++)
776 if (numShifts
> matchedBits
) {
777 matchedBits
= numShifts
;
782 memcpy(pBestRoute
, &table
->table
[matchedNdx
], sizeof(MIB_IPFORWARDROW
));
783 HeapFree(GetProcessHeap(), 0, table
);
787 ret
= ERROR_OUTOFMEMORY
;
788 TRACE("returning %ld\n", ret
);
792 /******************************************************************
793 * GetExtendedTcpTable (IPHLPAPI.@)
795 * Get the table of TCP endpoints available to the application.
798 * pTcpTable [Out] table struct with the filtered TCP endpoints available to application
799 * pdwSize [In/Out] estimated size of the structure returned in pTcpTable, in bytes
800 * bOrder [In] whether to order the table
801 * ulAf [in] version of IP used by the TCP endpoints
802 * TableClass [in] type of the TCP table structure from TCP_TABLE_CLASS
803 * Reserved [in] reserved - this value must be zero
807 * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER
811 DWORD WINAPI
GetExtendedTcpTable(PVOID pTcpTable
, PDWORD pdwSize
, BOOL bOrder
, ULONG ulAf
, TCP_TABLE_CLASS TableClass
, ULONG Reserved
)
813 DWORD ret
= NO_ERROR
;
819 /******************************************************************
820 * GetFriendlyIfIndex (IPHLPAPI.@)
832 DWORD WINAPI
GetFriendlyIfIndex(DWORD IfIndex
)
834 /* windows doesn't validate these, either, just makes sure the top byte is
835 cleared. I assume my ifenum module never gives an index with the top
837 TRACE("returning %ld\n", IfIndex
);
842 /******************************************************************
843 * GetIcmpStatistics (IPHLPAPI.@)
855 DWORD WINAPI
GetIcmpStatistics(PMIB_ICMP pStats
)
859 TRACE("pStats %p\n", pStats
);
860 ret
= getICMPStats(pStats
);
861 TRACE("returning %ld\n", ret
);
866 /******************************************************************
867 * GetIfEntry (IPHLPAPI.@)
879 DWORD WINAPI
GetIfEntry(PMIB_IFROW pIfRow
)
884 TRACE("pIfRow %p\n", pIfRow
);
886 return ERROR_INVALID_PARAMETER
;
888 name
= getInterfaceNameByIndex(pIfRow
->dwIndex
);
890 ret
= getInterfaceEntryByIndex(pIfRow
->dwIndex
, pIfRow
);
892 ret
= getInterfaceStatsByName(name
, pIfRow
);
893 consumeInterfaceName(name
);
896 ret
= ERROR_INVALID_DATA
;
897 TRACE("returning %ld\n", ret
);
902 static int IfTableSorter(const void *a
, const void *b
)
907 ret
= ((PMIB_IFROW
)a
)->dwIndex
- ((PMIB_IFROW
)b
)->dwIndex
;
914 /******************************************************************
915 * GetIfTable (IPHLPAPI.@)
929 DWORD WINAPI
GetIfTable(PMIB_IFTABLE pIfTable
, PULONG pdwSize
, BOOL bOrder
)
933 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize
, pdwSize
,
936 ret
= ERROR_INVALID_PARAMETER
;
938 DWORD numInterfaces
= getNumInterfaces();
940 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces
);
941 size
= sizeof(MIB_IFTABLE
) + (numInterfaces
- 1) * sizeof(MIB_IFROW
);
943 if (!pIfTable
|| *pdwSize
< size
) {
945 ret
= ERROR_INSUFFICIENT_BUFFER
;
948 InterfaceIndexTable
*table
= getInterfaceIndexTable();
951 size
= sizeof(MIB_IFTABLE
) + (table
->numIndexes
- 1) *
953 if (*pdwSize
< size
) {
955 ret
= ERROR_INSUFFICIENT_BUFFER
;
960 pIfTable
->dwNumEntries
= 0;
961 for (ndx
= 0; ndx
< table
->numIndexes
; ndx
++) {
962 pIfTable
->table
[ndx
].dwIndex
= table
->indexes
[ndx
];
963 GetIfEntry(&pIfTable
->table
[ndx
]);
964 pIfTable
->dwNumEntries
++;
967 qsort(pIfTable
->table
, pIfTable
->dwNumEntries
, sizeof(MIB_IFROW
),
974 ret
= ERROR_OUTOFMEMORY
;
977 TRACE("returning %ld\n", ret
);
982 /******************************************************************
983 * GetInterfaceInfo (IPHLPAPI.@)
989 * dwOutBufLen [In/Out]
996 DWORD WINAPI
GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable
, PULONG dwOutBufLen
)
1000 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable
, dwOutBufLen
);
1002 ret
= ERROR_INVALID_PARAMETER
;
1004 DWORD numNonLoopbackInterfaces
= getNumNonLoopbackInterfaces();
1006 TRACE("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces
);
1007 size
= sizeof(IP_INTERFACE_INFO
) + (numNonLoopbackInterfaces
) *
1008 sizeof(IP_ADAPTER_INDEX_MAP
);
1010 if (!pIfTable
|| *dwOutBufLen
< size
) {
1011 *dwOutBufLen
= size
;
1012 ret
= ERROR_INSUFFICIENT_BUFFER
;
1015 InterfaceIndexTable
*table
= getNonLoopbackInterfaceIndexTable();
1018 TRACE("table->numIndexes == 0x%x\n", table
->numIndexes
);
1019 size
= sizeof(IP_INTERFACE_INFO
) + (table
->numIndexes
) *
1020 sizeof(IP_ADAPTER_INDEX_MAP
);
1021 if (*dwOutBufLen
< size
) {
1022 *dwOutBufLen
= size
;
1023 ret
= ERROR_INSUFFICIENT_BUFFER
;
1028 pIfTable
->NumAdapters
= 0;
1029 for (ndx
= 0; ndx
< table
->numIndexes
; ndx
++) {
1030 const char *walker
, *name
;
1033 pIfTable
->Adapter
[ndx
].Index
= table
->indexes
[ndx
];
1034 name
= getInterfaceNameByIndex(table
->indexes
[ndx
]);
1035 for (walker
= name
, assigner
= pIfTable
->Adapter
[ndx
].Name
;
1036 walker
&& *walker
&&
1037 assigner
- pIfTable
->Adapter
[ndx
].Name
< MAX_ADAPTER_NAME
- 1;
1038 walker
++, assigner
++)
1039 *assigner
= *walker
;
1041 consumeInterfaceName(name
);
1042 pIfTable
->NumAdapters
++;
1049 ret
= ERROR_OUTOFMEMORY
;
1052 TRACE("returning %ld\n", ret
);
1057 static int IpAddrTableSorter(const void *a
, const void *b
)
1062 ret
= ((PMIB_IPADDRROW
)a
)->dwAddr
- ((PMIB_IPADDRROW
)b
)->dwAddr
;
1069 /******************************************************************
1070 * GetIpAddrTable (IPHLPAPI.@)
1075 * pIpAddrTable [In/Out]
1084 DWORD WINAPI
GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable
, PULONG pdwSize
, BOOL bOrder
)
1088 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable
, pdwSize
,
1091 ret
= ERROR_INVALID_PARAMETER
;
1093 DWORD numInterfaces
= getNumInterfaces();
1094 ULONG size
= sizeof(MIB_IPADDRTABLE
) + (numInterfaces
- 1) *
1095 sizeof(MIB_IPADDRROW
);
1097 if (!pIpAddrTable
|| *pdwSize
< size
) {
1099 ret
= ERROR_INSUFFICIENT_BUFFER
;
1102 InterfaceIndexTable
*table
= getInterfaceIndexTable();
1105 size
= sizeof(MIB_IPADDRTABLE
) + (table
->numIndexes
- 1) *
1106 sizeof(MIB_IPADDRROW
);
1107 if (*pdwSize
< size
) {
1109 ret
= ERROR_INSUFFICIENT_BUFFER
;
1114 pIpAddrTable
->dwNumEntries
= 0;
1115 for (ndx
= 0; ndx
< table
->numIndexes
; ndx
++) {
1116 pIpAddrTable
->table
[ndx
].dwIndex
= table
->indexes
[ndx
];
1117 pIpAddrTable
->table
[ndx
].dwAddr
=
1118 getInterfaceIPAddrByIndex(table
->indexes
[ndx
]);
1119 pIpAddrTable
->table
[ndx
].dwMask
=
1120 getInterfaceMaskByIndex(table
->indexes
[ndx
]);
1121 /* the dwBCastAddr member isn't the broadcast address, it indicates
1122 * whether the interface uses the 1's broadcast address (1) or the
1123 * 0's broadcast address (0).
1125 bcast
= getInterfaceBCastAddrByIndex(table
->indexes
[ndx
]);
1126 pIpAddrTable
->table
[ndx
].dwBCastAddr
=
1127 (bcast
& pIpAddrTable
->table
[ndx
].dwMask
) ? 1 : 0;
1128 /* FIXME: hardcoded reasm size, not sure where to get it */
1129 pIpAddrTable
->table
[ndx
].dwReasmSize
= 65535;
1130 pIpAddrTable
->table
[ndx
].unused1
= 0;
1131 pIpAddrTable
->table
[ndx
].wType
= 0; /* aka unused2 */
1132 pIpAddrTable
->dwNumEntries
++;
1135 qsort(pIpAddrTable
->table
, pIpAddrTable
->dwNumEntries
,
1136 sizeof(MIB_IPADDRROW
), IpAddrTableSorter
);
1142 ret
= ERROR_OUTOFMEMORY
;
1145 TRACE("returning %ld\n", ret
);
1150 static int IpForwardTableSorter(const void *a
, const void *b
)
1155 PMIB_IPFORWARDROW rowA
= (PMIB_IPFORWARDROW
)a
, rowB
= (PMIB_IPFORWARDROW
)b
;
1157 ret
= rowA
->dwForwardDest
- rowB
->dwForwardDest
;
1159 ret
= rowA
->dwForwardProto
- rowB
->dwForwardProto
;
1161 ret
= rowA
->dwForwardPolicy
- rowB
->dwForwardPolicy
;
1163 ret
= rowA
->dwForwardNextHop
- rowB
->dwForwardNextHop
;
1173 /******************************************************************
1174 * GetIpForwardTable (IPHLPAPI.@)
1179 * pIpForwardTable [In/Out]
1188 DWORD WINAPI
GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable
, PULONG pdwSize
, BOOL bOrder
)
1192 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable
,
1193 pdwSize
, (DWORD
)bOrder
);
1195 ret
= ERROR_INVALID_PARAMETER
;
1197 DWORD numRoutes
= getNumRoutes();
1198 ULONG sizeNeeded
= sizeof(MIB_IPFORWARDTABLE
) + (numRoutes
- 1) *
1199 sizeof(MIB_IPFORWARDROW
);
1201 if (!pIpForwardTable
|| *pdwSize
< sizeNeeded
) {
1202 *pdwSize
= sizeNeeded
;
1203 ret
= ERROR_INSUFFICIENT_BUFFER
;
1206 RouteTable
*table
= getRouteTable();
1208 sizeNeeded
= sizeof(MIB_IPFORWARDTABLE
) + (table
->numRoutes
- 1) *
1209 sizeof(MIB_IPFORWARDROW
);
1210 if (*pdwSize
< sizeNeeded
) {
1211 *pdwSize
= sizeNeeded
;
1212 ret
= ERROR_INSUFFICIENT_BUFFER
;
1217 pIpForwardTable
->dwNumEntries
= table
->numRoutes
;
1218 for (ndx
= 0; ndx
< numRoutes
; ndx
++) {
1219 pIpForwardTable
->table
[ndx
].dwForwardIfIndex
=
1220 table
->routes
[ndx
].ifIndex
+ 1;
1221 pIpForwardTable
->table
[ndx
].dwForwardDest
=
1222 table
->routes
[ndx
].dest
;
1223 pIpForwardTable
->table
[ndx
].dwForwardMask
=
1224 table
->routes
[ndx
].mask
;
1225 pIpForwardTable
->table
[ndx
].dwForwardPolicy
= 0;
1226 pIpForwardTable
->table
[ndx
].dwForwardNextHop
=
1227 table
->routes
[ndx
].gateway
;
1228 /* FIXME: this type is appropriate for local interfaces; may not
1229 always be appropriate */
1230 pIpForwardTable
->table
[ndx
].dwForwardType
= MIB_IPROUTE_TYPE_DIRECT
;
1231 /* FIXME: other protos might be appropriate, e.g. the default route
1232 is typically set with MIB_IPPROTO_NETMGMT instead */
1233 pIpForwardTable
->table
[ndx
].dwForwardProto
= MIB_IPPROTO_LOCAL
;
1234 /* punt on age and AS */
1235 pIpForwardTable
->table
[ndx
].dwForwardAge
= 0;
1236 pIpForwardTable
->table
[ndx
].dwForwardNextHopAS
= 0;
1237 pIpForwardTable
->table
[ndx
].dwForwardMetric1
=
1238 table
->routes
[ndx
].metric
;
1239 /* rest of the metrics are 0.. */
1240 pIpForwardTable
->table
[ndx
].dwForwardMetric2
= 0;
1241 pIpForwardTable
->table
[ndx
].dwForwardMetric3
= 0;
1242 pIpForwardTable
->table
[ndx
].dwForwardMetric4
= 0;
1243 pIpForwardTable
->table
[ndx
].dwForwardMetric5
= 0;
1246 qsort(pIpForwardTable
->table
, pIpForwardTable
->dwNumEntries
,
1247 sizeof(MIB_IPFORWARDROW
), IpForwardTableSorter
);
1250 HeapFree(GetProcessHeap(), 0, table
);
1253 ret
= ERROR_OUTOFMEMORY
;
1256 TRACE("returning %ld\n", ret
);
1261 static int IpNetTableSorter(const void *a
, const void *b
)
1266 ret
= ((PMIB_IPNETROW
)a
)->dwAddr
- ((PMIB_IPNETROW
)b
)->dwAddr
;
1273 /******************************************************************
1274 * GetIpNetTable (IPHLPAPI.@)
1279 * pIpNetTable [In/Out]
1288 DWORD WINAPI
GetIpNetTable(PMIB_IPNETTABLE pIpNetTable
, PULONG pdwSize
, BOOL bOrder
)
1290 DWORD ret
= NO_ERROR
;
1292 TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable
, pdwSize
,
1295 ret
= ERROR_INVALID_PARAMETER
;
1297 DWORD numEntries
= getNumArpEntries();
1298 ULONG size
= sizeof(MIB_IPNETTABLE
);
1301 size
+= (numEntries
- 1) * sizeof(MIB_IPNETROW
);
1302 if (!pIpNetTable
|| *pdwSize
< size
) {
1304 ret
= ERROR_INSUFFICIENT_BUFFER
;
1307 PMIB_IPNETTABLE table
= getArpTable();
1309 size
= sizeof(MIB_IPNETTABLE
);
1310 if (table
->dwNumEntries
> 1)
1311 size
+= (table
->dwNumEntries
- 1) * sizeof(MIB_IPNETROW
);
1312 if (*pdwSize
< size
) {
1314 ret
= ERROR_INSUFFICIENT_BUFFER
;
1318 memcpy(pIpNetTable
, table
, size
);
1320 qsort(pIpNetTable
->table
, pIpNetTable
->dwNumEntries
,
1321 sizeof(MIB_IPNETROW
), IpNetTableSorter
);
1324 HeapFree(GetProcessHeap(), 0, table
);
1328 TRACE("returning %d\n", ret
);
1333 /******************************************************************
1334 * GetIpStatistics (IPHLPAPI.@)
1346 DWORD WINAPI
GetIpStatistics(PMIB_IPSTATS pStats
)
1348 return GetIpStatisticsEx(pStats
, PF_INET
);
1351 /******************************************************************
1352 * GetIpStatisticsEx (IPHLPAPI.@)
1365 DWORD WINAPI
GetIpStatisticsEx(PMIB_IPSTATS pStats
, DWORD dwFamily
)
1369 TRACE("pStats %p\n", pStats
);
1370 ret
= getIPStats(pStats
, dwFamily
);
1371 TRACE("returning %ld\n", ret
);
1375 /******************************************************************
1376 * GetNetworkParams (IPHLPAPI.@)
1381 * pFixedInfo [In/Out]
1382 * pOutBufLen [In/Out]
1389 DWORD WINAPI
GetNetworkParams(PFIXED_INFO pFixedInfo
, PULONG pOutBufLen
)
1394 PIPHLP_RES_INFO resInfo
;
1396 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo
, pOutBufLen
);
1398 return ERROR_INVALID_PARAMETER
;
1400 resInfo
= getResInfo();
1402 return ERROR_OUTOFMEMORY
;
1404 size
= sizeof(FIXED_INFO
) + (resInfo
->riCount
> 1 ? (resInfo
->riCount
-1) *
1405 sizeof(IP_ADDR_STRING
) : 0);
1406 if (!pFixedInfo
|| *pOutBufLen
< size
) {
1408 disposeResInfo( resInfo
);
1409 return ERROR_BUFFER_OVERFLOW
;
1412 memset(pFixedInfo
, 0, size
);
1413 size
= sizeof(pFixedInfo
->HostName
);
1414 GetComputerNameExA(ComputerNameDnsHostname
, pFixedInfo
->HostName
, &size
);
1415 size
= sizeof(pFixedInfo
->DomainName
);
1416 GetComputerNameExA(ComputerNameDnsDomain
, pFixedInfo
->DomainName
, &size
);
1418 TRACE("GetComputerNameExA: %s\n", pFixedInfo
->DomainName
);
1420 if (resInfo
->riCount
> 0)
1422 CopyMemory(&pFixedInfo
->DnsServerList
, resInfo
->DnsList
, sizeof(IP_ADDR_STRING
));
1423 if (resInfo
->riCount
> 1)
1425 IP_ADDR_STRING
*pSrc
= resInfo
->DnsList
->Next
;
1426 IP_ADDR_STRING
*pTarget
= (struct _IP_ADDR_STRING
*)((char*)pFixedInfo
+ sizeof(FIXED_INFO
));
1428 pFixedInfo
->DnsServerList
.Next
= pTarget
;
1432 CopyMemory(pTarget
, pSrc
, sizeof(IP_ADDR_STRING
));
1434 if (resInfo
->riCount
> 1)
1436 pTarget
->Next
= (IP_ADDR_STRING
*)((char*)pTarget
+ sizeof(IP_ADDR_STRING
));
1437 pTarget
= pTarget
->Next
;
1442 pTarget
->Next
= NULL
;
1450 pFixedInfo
->DnsServerList
.Next
= NULL
;
1454 pFixedInfo
->NodeType
= HYBRID_NODETYPE
;
1455 regReturn
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
1456 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ
, &hKey
);
1457 if (regReturn
!= ERROR_SUCCESS
)
1458 regReturn
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
1459 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ
,
1461 if (regReturn
== ERROR_SUCCESS
)
1463 DWORD size
= sizeof(pFixedInfo
->ScopeId
);
1465 RegQueryValueExA(hKey
, "ScopeID", NULL
, NULL
, (PBYTE
)pFixedInfo
->ScopeId
, &size
);
1469 disposeResInfo( resInfo
);
1470 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
1471 I suppose could also check for a listener on port 53 to set EnableDns */
1473 TRACE("returning %ld\n", ret
);
1479 /******************************************************************
1480 * GetNumberOfInterfaces (IPHLPAPI.@)
1492 DWORD WINAPI
GetNumberOfInterfaces(PDWORD pdwNumIf
)
1496 TRACE("pdwNumIf %p\n", pdwNumIf
);
1498 ret
= ERROR_INVALID_PARAMETER
;
1500 *pdwNumIf
= getNumInterfaces();
1503 TRACE("returning %ld\n", ret
);
1508 /******************************************************************
1509 * GetOwnerModuleFromTcpEntry (IPHLPAPI.@)
1511 * Get data about the module that issued the context bind for a specific IPv4 TCP endpoint in a MIB table row
1514 * pTcpEntry [in] pointer to a MIB_TCPROW_OWNER_MODULE structure
1515 * Class [in] TCPIP_OWNER_MODULE_INFO_CLASS enumeration value
1516 * Buffer [out] pointer a buffer containing a TCPIP_OWNER_MODULE_BASIC_INFO structure with the owner module data.
1517 * pdwSize [in, out] estimated size of the structure returned in Buffer, in bytes
1521 * Failure: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY
1522 * ERROR_NOT_FOUND or ERROR_PARTIAL_COPY
1525 * The type of data returned in Buffer is indicated by the value of the Class parameter.
1527 DWORD WINAPI
GetOwnerModuleFromTcpEntry( PMIB_TCPROW_OWNER_MODULE pTcpEntry
, TCPIP_OWNER_MODULE_INFO_CLASS Class
, PVOID Buffer
, PDWORD pdwSize
)
1529 DWORD ret
= NO_ERROR
;
1535 /******************************************************************
1536 * GetPerAdapterInfo (IPHLPAPI.@)
1542 * pPerAdapterInfo [In/Out]
1543 * pOutBufLen [In/Out]
1550 static void CreateNameServerListEnumNamesFunc( PWCHAR Interface
, PWCHAR Server
, PVOID Data
)
1552 IP_ADDR_STRING
*pNext
;
1553 PNAME_SERVER_LIST_CONTEXT Context
= (PNAME_SERVER_LIST_CONTEXT
)Data
;
1555 if (!Context
->NumServers
)
1557 if (Context
->uSizeAvailable
>= Context
->uSizeRequired
)
1559 WideCharToMultiByte(CP_ACP
, 0, Server
, -1, Context
->pData
->DnsServerList
.IpAddress
.String
, 16, NULL
, NULL
);
1560 Context
->pData
->DnsServerList
.IpAddress
.String
[15] = '\0';
1561 Context
->pLastAddr
= &Context
->pData
->DnsServerList
;
1566 Context
->uSizeRequired
+= sizeof(IP_ADDR_STRING
);
1567 if (Context
->uSizeAvailable
>= Context
->uSizeRequired
)
1569 pNext
= (IP_ADDR_STRING
*)(((char*)Context
->pLastAddr
) + sizeof(IP_ADDR_STRING
));
1570 WideCharToMultiByte(CP_ACP
, 0, Server
, -1, pNext
->IpAddress
.String
, 16, NULL
, NULL
);
1571 pNext
->IpAddress
.String
[15] = '\0';
1572 Context
->pLastAddr
->Next
= pNext
;
1573 Context
->pLastAddr
= pNext
;
1577 Context
->NumServers
++;
1580 DWORD WINAPI
GetPerAdapterInfo(ULONG IfIndex
, PIP_PER_ADAPTER_INFO pPerAdapterInfo
, PULONG pOutBufLen
)
1585 NAME_SERVER_LIST_CONTEXT Context
;
1586 WCHAR keyname
[200] = L
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
1589 return ERROR_INVALID_PARAMETER
;
1591 if (!pPerAdapterInfo
|| *pOutBufLen
< sizeof(IP_PER_ADAPTER_INFO
))
1593 *pOutBufLen
= sizeof(IP_PER_ADAPTER_INFO
);
1594 return ERROR_BUFFER_OVERFLOW
;
1597 ifName
= getInterfaceNameByIndex(IfIndex
);
1599 return ERROR_INVALID_PARAMETER
;
1601 MultiByteToWideChar(CP_ACP
, 0, ifName
, -1, &keyname
[62], sizeof(keyname
)/sizeof(WCHAR
) - 63);
1602 HeapFree(GetProcessHeap(), 0, (LPVOID
)ifName
);
1604 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, keyname
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
1606 return ERROR_NOT_SUPPORTED
;
1608 Context
.NumServers
= 0;
1609 Context
.uSizeAvailable
= *pOutBufLen
;
1610 Context
.uSizeRequired
= sizeof(IP_PER_ADAPTER_INFO
);
1611 Context
.pData
= pPerAdapterInfo
;
1613 if (*pOutBufLen
>= sizeof(IP_PER_ADAPTER_INFO
))
1614 ZeroMemory(pPerAdapterInfo
, sizeof(IP_PER_ADAPTER_INFO
));
1616 EnumNameServers(hkey
, &keyname
[62], &Context
, CreateNameServerListEnumNamesFunc
);
1618 if (Context
.uSizeRequired
> Context
.uSizeAvailable
)
1620 *pOutBufLen
= Context
.uSizeRequired
;
1622 return ERROR_BUFFER_OVERFLOW
;
1625 if(RegQueryValueExW(hkey
, L
"DHCPNameServer", NULL
, NULL
, NULL
, &dwSize
) == ERROR_SUCCESS
)
1627 pPerAdapterInfo
->AutoconfigActive
= TRUE
;
1635 /******************************************************************
1636 * GetRTTAndHopCount (IPHLPAPI.@)
1641 * DestIpAddress [In]
1651 BOOL WINAPI
GetRTTAndHopCount(IPAddr DestIpAddress
, PULONG HopCount
, ULONG MaxHops
, PULONG RTT
)
1653 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
1654 DestIpAddress
, HopCount
, MaxHops
, RTT
);
1660 /******************************************************************
1661 * GetTcpStatisticsEx (IPHLPAPI.@)
1674 DWORD WINAPI
GetTcpStatisticsEx(PMIB_TCPSTATS pStats
, DWORD dwFamily
)
1678 TRACE("pStats %p\n", pStats
);
1679 ret
= getTCPStats(pStats
, dwFamily
);
1680 TRACE("returning %ld\n", ret
);
1684 /******************************************************************
1685 * GetTcpStatistics (IPHLPAPI.@)
1697 DWORD WINAPI
GetTcpStatistics(PMIB_TCPSTATS pStats
)
1699 return GetTcpStatisticsEx(pStats
, PF_INET
);
1703 static int TcpTableSorter(const void *a
, const void *b
)
1708 PMIB_TCPROW rowA
= (PMIB_TCPROW
)a
, rowB
= (PMIB_TCPROW
)b
;
1710 ret
= rowA
->dwLocalAddr
- rowB
->dwLocalAddr
;
1712 ret
= rowA
->dwLocalPort
- rowB
->dwLocalPort
;
1714 ret
= rowA
->dwRemoteAddr
- rowB
->dwRemoteAddr
;
1716 ret
= rowA
->dwRemotePort
- rowB
->dwRemotePort
;
1726 /******************************************************************
1727 * GetTcpTable (IPHLPAPI.@)
1729 * Get the table of active TCP connections.
1732 * pTcpTable [Out] buffer for TCP connections table
1733 * pdwSize [In/Out] length of output buffer
1734 * bOrder [In] whether to order the table
1738 * Failure: error code from winerror.h
1741 * If pdwSize is less than required, the function will return
1742 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to
1743 * the required byte size.
1744 * If bOrder is true, the returned table will be sorted, first by
1745 * local address and port number, then by remote address and port
1748 DWORD WINAPI
GetTcpTable(PMIB_TCPTABLE pTcpTable
, PDWORD pdwSize
, BOOL bOrder
)
1750 DWORD ret
= NO_ERROR
;
1752 TRACE("pTcpTable %p, pdwSize %p, bOrder %d\n", pTcpTable
, pdwSize
,
1755 ret
= ERROR_INVALID_PARAMETER
;
1757 DWORD numEntries
= getNumTcpEntries();
1758 DWORD size
= sizeof(MIB_TCPTABLE
);
1761 size
+= (numEntries
- 1) * sizeof(MIB_TCPROW
);
1762 if (!pTcpTable
|| *pdwSize
< size
) {
1764 ret
= ERROR_INSUFFICIENT_BUFFER
;
1767 PMIB_TCPTABLE pTcpTable
= getTcpTable();
1770 size
= sizeof(MIB_TCPTABLE
);
1771 if (pTcpTable
->dwNumEntries
> 1)
1772 size
+= (pTcpTable
->dwNumEntries
- 1) * sizeof(MIB_TCPROW
);
1776 qsort(pTcpTable
->table
, pTcpTable
->dwNumEntries
,
1777 sizeof(MIB_TCPROW
), TcpTableSorter
);
1782 TRACE("returning %d\n", ret
);
1787 /******************************************************************
1788 * GetUdpStatisticsEx (IPHLPAPI.@)
1801 DWORD WINAPI
GetUdpStatisticsEx(PMIB_UDPSTATS pStats
, DWORD dwFamily
)
1805 TRACE("pStats %p\n", pStats
);
1806 ret
= getUDPStats(pStats
, dwFamily
);
1807 TRACE("returning %ld\n", ret
);
1811 /******************************************************************
1812 * GetUdpStatistics (IPHLPAPI.@)
1824 DWORD WINAPI
GetUdpStatistics(PMIB_UDPSTATS pStats
)
1826 return GetUdpStatisticsEx(pStats
, PF_INET
);
1830 static int UdpTableSorter(const void *a
, const void *b
)
1835 PMIB_UDPROW rowA
= (PMIB_UDPROW
)a
, rowB
= (PMIB_UDPROW
)b
;
1837 ret
= rowA
->dwLocalAddr
- rowB
->dwLocalAddr
;
1839 ret
= rowA
->dwLocalPort
- rowB
->dwLocalPort
;
1847 /******************************************************************
1848 * GetUdpTable (IPHLPAPI.@)
1853 * pUdpTable [In/Out]
1862 DWORD WINAPI
GetUdpTable(PMIB_UDPTABLE pUdpTable
, PDWORD pdwSize
, BOOL bOrder
)
1866 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable
, pdwSize
,
1869 ret
= ERROR_INVALID_PARAMETER
;
1871 DWORD numEntries
= getNumUdpEntries();
1872 ULONG size
= sizeof(MIB_UDPTABLE
) + (numEntries
- 1) * sizeof(MIB_UDPROW
);
1874 if (!pUdpTable
|| *pdwSize
< size
) {
1876 ret
= ERROR_INSUFFICIENT_BUFFER
;
1879 PMIB_UDPTABLE table
= getUdpTable();
1882 size
= sizeof(MIB_UDPTABLE
) + (table
->dwNumEntries
- 1) *
1884 if (*pdwSize
< size
) {
1886 ret
= ERROR_INSUFFICIENT_BUFFER
;
1889 memcpy(pUdpTable
, table
, size
);
1891 qsort(pUdpTable
->table
, pUdpTable
->dwNumEntries
,
1892 sizeof(MIB_UDPROW
), UdpTableSorter
);
1898 ret
= ERROR_OUTOFMEMORY
;
1901 TRACE("returning %ld\n", ret
);
1906 /******************************************************************
1907 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1909 * This is a Win98-only function to get information on "unidirectional"
1910 * adapters. Since this is pretty nonsensical in other contexts, it
1911 * never returns anything.
1914 * pIPIfInfo [Out] buffer for adapter infos
1915 * dwOutBufLen [Out] length of the output buffer
1919 * Failure: error code from winerror.h
1922 * Stub, returns ERROR_NOT_SUPPORTED.
1924 DWORD WINAPI
GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo
, PULONG dwOutBufLen
)
1926 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo
, dwOutBufLen
);
1927 /* a unidirectional adapter?? not bloody likely! */
1928 return ERROR_NOT_SUPPORTED
;
1932 /******************************************************************
1933 * IpReleaseAddress (IPHLPAPI.@)
1935 * Release an IP obtained through DHCP,
1938 * AdapterInfo [In] adapter to release IP address
1942 * Failure: error code from winerror.h
1945 DWORD WINAPI
IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo
)
1947 COMM_DHCP_REPLY Reply
;
1948 COMM_DHCP_REQ Request
;
1951 Request
.AdapterIndex
= AdapterInfo
->Index
;
1952 Request
.Type
= DhcpReqReleaseIpAddress
;
1954 TRACE("AdapterInfo %p\n", AdapterInfo
);
1956 if (CallNamedPipe(DHCP_PIPE_NAME
,
1962 NMPWAIT_USE_DEFAULT_WAIT
))
1967 return ERROR_INVALID_PARAMETER
;
1970 return ERROR_PROC_NOT_FOUND
;
1974 /******************************************************************
1975 * IpRenewAddress (IPHLPAPI.@)
1977 * Renew an IP obtained through DHCP.
1980 * AdapterInfo [In] adapter to renew IP address
1984 * Failure: error code from winerror.h
1986 DWORD WINAPI
IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo
)
1988 COMM_DHCP_REPLY Reply
;
1989 COMM_DHCP_REQ Request
;
1992 Request
.AdapterIndex
= AdapterInfo
->Index
;
1993 Request
.Type
= DhcpReqRenewIpAddress
;
1995 TRACE("AdapterInfo %p\n", AdapterInfo
);
1997 if (CallNamedPipe(DHCP_PIPE_NAME
,
2003 NMPWAIT_USE_DEFAULT_WAIT
))
2008 return ERROR_INVALID_PARAMETER
;
2011 return ERROR_PROC_NOT_FOUND
;
2015 /******************************************************************
2016 * NotifyAddrChange (IPHLPAPI.@)
2018 * Notify caller whenever the ip-interface map is changed.
2021 * Handle [Out] handle usable in asynchronous notification
2022 * overlapped [In] overlapped structure that notifies the caller
2026 * Failure: error code from winerror.h
2029 * Stub, returns ERROR_NOT_SUPPORTED.
2031 DWORD WINAPI
NotifyAddrChange(PHANDLE Handle
, LPOVERLAPPED overlapped
)
2033 FIXME("(Handle %p, overlapped %p): stub\n", Handle
, overlapped
);
2034 return ERROR_NOT_SUPPORTED
;
2038 /******************************************************************
2039 * NotifyRouteChange (IPHLPAPI.@)
2041 * Notify caller whenever the ip routing table is changed.
2044 * Handle [Out] handle usable in asynchronous notification
2045 * overlapped [In] overlapped structure that notifies the caller
2049 * Failure: error code from winerror.h
2052 * Stub, returns ERROR_NOT_SUPPORTED.
2054 DWORD WINAPI
NotifyRouteChange(PHANDLE Handle
, LPOVERLAPPED overlapped
)
2056 FIXME("(Handle %p, overlapped %p): stub\n", Handle
, overlapped
);
2057 return ERROR_NOT_SUPPORTED
;
2061 /******************************************************************
2062 * SendARP (IPHLPAPI.@)
2064 * Send an ARP request.
2067 * DestIP [In] attempt to obtain this IP
2068 * SrcIP [In] optional sender IP address
2069 * pMacAddr [Out] buffer for the mac address
2070 * PhyAddrLen [In/Out] length of the output buffer
2074 * Failure: error code from winerror.h
2077 * Stub, returns ERROR_NOT_SUPPORTED.
2079 DWORD WINAPI
SendARP(IPAddr DestIP
, IPAddr SrcIP
, PULONG pMacAddr
, PULONG PhyAddrLen
)
2081 FIXME("(DestIP 0x%08x, SrcIP 0x%08x, pMacAddr %p, PhyAddrLen %p): stub\n",
2082 DestIP
, SrcIP
, pMacAddr
, PhyAddrLen
);
2083 return ERROR_NOT_SUPPORTED
;
2087 /******************************************************************
2088 * SetIfEntry (IPHLPAPI.@)
2090 * Set the administrative status of an interface.
2093 * pIfRow [In] dwAdminStatus member specifies the new status.
2097 * Failure: error code from winerror.h
2100 * Stub, returns ERROR_NOT_SUPPORTED.
2102 DWORD WINAPI
SetIfEntry(PMIB_IFROW pIfRow
)
2104 FIXME("(pIfRow %p): stub\n", pIfRow
);
2105 /* this is supposed to set an interface administratively up or down.
2106 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
2107 this sort of down is indistinguishable from other sorts of down (e.g. no
2109 return ERROR_NOT_SUPPORTED
;
2113 /******************************************************************
2114 * SetIpForwardEntry (IPHLPAPI.@)
2116 * Modify an existing route.
2119 * pRoute [In] route with the new information
2123 * Failure: error code from winerror.h
2126 DWORD WINAPI
SetIpForwardEntry(PMIB_IPFORWARDROW pRoute
)
2128 return setIpForwardEntry( pRoute
);
2132 /******************************************************************
2133 * SetIpNetEntry (IPHLPAPI.@)
2135 * Modify an existing ARP entry.
2138 * pArpEntry [In] ARP entry with the new information
2142 * Failure: error code from winerror.h
2144 DWORD WINAPI
SetIpNetEntry(PMIB_IPNETROW pArpEntry
)
2148 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req
=
2149 TCP_REQUEST_SET_INFORMATION_INIT
;
2152 PMIB_IPNETROW arpBuff
;
2155 return ERROR_INVALID_PARAMETER
;
2157 if (!NT_SUCCESS(openTcpFile( &tcpFile
)))
2158 return ERROR_NOT_SUPPORTED
;
2160 if (!NT_SUCCESS(getNthIpEntity( tcpFile
, pArpEntry
->dwIndex
, &id
)))
2162 closeTcpFile(tcpFile
);
2163 return ERROR_INVALID_PARAMETER
;
2166 req
.Req
.ID
.toi_class
= INFO_CLASS_PROTOCOL
;
2167 req
.Req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
2168 req
.Req
.ID
.toi_id
= IP_MIB_ARPTABLE_ENTRY_ID
;
2169 req
.Req
.ID
.toi_entity
.tei_instance
= id
.tei_instance
;
2170 req
.Req
.ID
.toi_entity
.tei_entity
= AT_ENTITY
;
2171 req
.Req
.BufferSize
= sizeof(MIB_IPNETROW
);
2172 arpBuff
= (PMIB_IPNETROW
)&req
.Req
.Buffer
[0];
2174 RtlCopyMemory(arpBuff
, pArpEntry
, sizeof(MIB_IPNETROW
));
2176 status
= DeviceIoControl( tcpFile
,
2177 IOCTL_TCP_SET_INFORMATION_EX
,
2185 closeTcpFile(tcpFile
);
2190 return ERROR_INVALID_PARAMETER
;
2194 /******************************************************************
2195 * SetIpStatistics (IPHLPAPI.@)
2197 * Toggle IP forwarding and det the default TTL value.
2200 * pIpStats [In] IP statistics with the new information
2204 * Failure: error code from winerror.h
2207 * Stub, returns NO_ERROR.
2209 DWORD WINAPI
SetIpStatistics(PMIB_IPSTATS pIpStats
)
2211 FIXME("(pIpStats %p): stub\n", pIpStats
);
2216 /******************************************************************
2217 * SetIpTTL (IPHLPAPI.@)
2219 * Set the default TTL value.
2222 * nTTL [In] new TTL value
2226 * Failure: error code from winerror.h
2229 * Stub, returns NO_ERROR.
2231 DWORD WINAPI
SetIpTTL(UINT nTTL
)
2233 FIXME("(nTTL %d): stub\n", nTTL
);
2238 /******************************************************************
2239 * SetTcpEntry (IPHLPAPI.@)
2241 * Set the state of a TCP connection.
2244 * pTcpRow [In] specifies connection with new state
2248 * Failure: error code from winerror.h
2251 * Stub, returns NO_ERROR.
2253 DWORD WINAPI
SetTcpEntry(PMIB_TCPROW pTcpRow
)
2255 FIXME("(pTcpRow %p): stub\n", pTcpRow
);
2260 /******************************************************************
2261 * UnenableRouter (IPHLPAPI.@)
2263 * Decrement the IP-forwarding reference count. Turn off IP-forwarding
2264 * if it reaches zero.
2267 * pOverlapped [In/Out] should be the same as in EnableRouter()
2268 * lpdwEnableCount [Out] optional, receives reference count
2272 * Failure: error code from winerror.h
2275 * Stub, returns ERROR_NOT_SUPPORTED.
2277 DWORD WINAPI
UnenableRouter(OVERLAPPED
* pOverlapped
, LPDWORD lpdwEnableCount
)
2279 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped
,
2281 return ERROR_NOT_SUPPORTED
;
2287 DWORD WINAPI
GetIpErrorString(IP_STATUS ErrorCode
,PWCHAR Buffer
,PDWORD Size
)
2297 PIP_ADAPTER_ORDER_MAP WINAPI
GetAdapterOrderMap(VOID
)
2306 DWORD WINAPI
GetAdaptersAddresses(ULONG Family
,ULONG Flags
,PVOID Reserved
,PIP_ADAPTER_ADDRESSES pAdapterAddresses
,PULONG pOutBufLen
)
2308 if (!pOutBufLen
) return ERROR_INVALID_PARAMETER
;
2309 if (!pAdapterAddresses
|| *pOutBufLen
== 0)
2310 return ERROR_BUFFER_OVERFLOW
;
2311 if (Reserved
) return ERROR_INVALID_PARAMETER
;
2314 return ERROR_NO_DATA
;
2320 BOOL WINAPI
CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped
)
2329 DWORD WINAPI
GetBestInterfaceEx(struct sockaddr
*pDestAddr
,PDWORD pdwBestIfIndex
)
2338 DWORD WINAPI
NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO
**ppTable
,PDWORD pdwCount
,BOOL bOrder
,HANDLE hHeap
,DWORD dwFlags
)
2347 DWORD WINAPI
GetIcmpStatisticsEx(PMIB_ICMP_EX pStats
,DWORD dwFamily
)
2353 /******************************************************************
2354 * GetIfTable2 (IPHLPAPI.@)
2360 NETIOAPI_API WINAPI
GetIfTable2(PMIB_IF_TABLE2
*pIfTable
)
2363 return ERROR_NOT_SUPPORTED
;
2366 /******************************************************************
2367 * GetIfEntry2 (IPHLPAPI.@)
2372 NETIOAPI_API WINAPI
GetIfEntry2(IN OUT PMIB_IF_ROW2 pIfRow
)
2374 TRACE("pIfRow %p\n", pIfRow
);
2376 return ERROR_INVALID_PARAMETER
;
2379 return ERROR_NOT_SUPPORTED
;
2383 SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute
)
2385 FIXME("SetIpForwardEntryToStack() stub\n");
2390 NhGetInterfaceNameFromDeviceGuid(DWORD dwUnknown1
,
2396 FIXME("NhGetInterfaceNameFromDeviceGuid() stub\n");