iphlpapi: Report NO_ERROR when IcmpSendEcho() succeeded.
[wine.git] / dlls / iphlpapi / tests / iphlpapi.c
blob609abb3762c807fdc241805875a3e39b522f0d16
1 /*
2 * iphlpapi dll test
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 St, Fifth Floor, Boston, MA 02110-1301, USA
22 * Some observations that an automated test can't produce:
23 * An adapter index is a key for an adapter. That is, if an index is returned
24 * from one API, that same index may be used successfully in another API, as
25 * long as the adapter remains present.
26 * If the adapter is removed and reinserted, however, the index may change (and
27 * indeed it does change on Win2K).
29 * The Name field of the IP_ADAPTER_INDEX_MAP entries returned by
30 * GetInterfaceInfo is declared as a wide string, but the bytes are actually
31 * an ASCII string on some versions of the IP helper API under Win9x. This was
32 * apparently an MS bug, it's corrected in later versions.
34 * The DomainName field of FIXED_INFO isn't NULL-terminated on Win98.
37 #include <stdarg.h>
38 #include "winsock2.h"
39 #include "windef.h"
40 #include "winbase.h"
41 #include "ws2tcpip.h"
42 #include "iphlpapi.h"
43 #include "iprtrmib.h"
44 #include "netioapi.h"
45 #include "wine/test.h"
46 #include <stdio.h>
47 #include <stdlib.h>
49 #define ICMP_MINLEN 8 /* copied from dlls/iphlpapi/ip_icmp.h file */
51 static HMODULE hLibrary = NULL;
53 static DWORD (WINAPI *pAllocateAndGetTcpExTableFromStack)(void**,BOOL,HANDLE,DWORD,DWORD);
54 static DWORD (WINAPI *pGetNumberOfInterfaces)(PDWORD);
55 static DWORD (WINAPI *pGetIpAddrTable)(PMIB_IPADDRTABLE,PULONG,BOOL);
56 static DWORD (WINAPI *pGetIfEntry)(PMIB_IFROW);
57 static DWORD (WINAPI *pGetIfEntry2)(PMIB_IF_ROW2);
58 static DWORD (WINAPI *pGetFriendlyIfIndex)(DWORD);
59 static DWORD (WINAPI *pGetIfTable)(PMIB_IFTABLE,PULONG,BOOL);
60 static DWORD (WINAPI *pGetIfTable2)(PMIB_IF_TABLE2*);
61 static DWORD (WINAPI *pGetIfTable2Ex)(MIB_IF_TABLE_LEVEL,PMIB_IF_TABLE2*);
62 static DWORD (WINAPI *pGetIpForwardTable)(PMIB_IPFORWARDTABLE,PULONG,BOOL);
63 static DWORD (WINAPI *pGetIpNetTable)(PMIB_IPNETTABLE,PULONG,BOOL);
64 static DWORD (WINAPI *pGetInterfaceInfo)(PIP_INTERFACE_INFO,PULONG);
65 static DWORD (WINAPI *pGetAdaptersInfo)(PIP_ADAPTER_INFO,PULONG);
66 static DWORD (WINAPI *pGetNetworkParams)(PFIXED_INFO,PULONG);
67 static DWORD (WINAPI *pGetIcmpStatistics)(PMIB_ICMP);
68 static DWORD (WINAPI *pGetIpStatistics)(PMIB_IPSTATS);
69 static DWORD (WINAPI *pGetTcpStatistics)(PMIB_TCPSTATS);
70 static DWORD (WINAPI *pGetUdpStatistics)(PMIB_UDPSTATS);
71 static DWORD (WINAPI *pGetIcmpStatisticsEx)(PMIB_ICMP_EX,DWORD);
72 static DWORD (WINAPI *pGetIpStatisticsEx)(PMIB_IPSTATS,DWORD);
73 static DWORD (WINAPI *pGetTcpStatisticsEx)(PMIB_TCPSTATS,DWORD);
74 static DWORD (WINAPI *pGetUdpStatisticsEx)(PMIB_UDPSTATS,DWORD);
75 static DWORD (WINAPI *pGetTcpTable)(PMIB_TCPTABLE,PDWORD,BOOL);
76 static DWORD (WINAPI *pGetUdpTable)(PMIB_UDPTABLE,PDWORD,BOOL);
77 static DWORD (WINAPI *pGetPerAdapterInfo)(ULONG,PIP_PER_ADAPTER_INFO,PULONG);
78 static DWORD (WINAPI *pGetAdaptersAddresses)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG);
79 static DWORD (WINAPI *pGetUnicastIpAddressEntry)(MIB_UNICASTIPADDRESS_ROW*);
80 static DWORD (WINAPI *pGetUnicastIpAddressTable)(ADDRESS_FAMILY,MIB_UNICASTIPADDRESS_TABLE**);
81 static DWORD (WINAPI *pNotifyAddrChange)(PHANDLE,LPOVERLAPPED);
82 static BOOL (WINAPI *pCancelIPChangeNotify)(LPOVERLAPPED);
83 static DWORD (WINAPI *pGetExtendedTcpTable)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG);
84 static DWORD (WINAPI *pGetExtendedUdpTable)(PVOID,PDWORD,BOOL,ULONG,UDP_TABLE_CLASS,ULONG);
85 static DWORD (WINAPI *pSetTcpEntry)(PMIB_TCPROW);
86 static HANDLE(WINAPI *pIcmpCreateFile)(VOID);
87 static DWORD (WINAPI *pIcmpSendEcho)(HANDLE,IPAddr,LPVOID,WORD,PIP_OPTION_INFORMATION,LPVOID,DWORD,DWORD);
88 static DWORD (WINAPI *pCreateSortedAddressPairs)(const PSOCKADDR_IN6,ULONG,const PSOCKADDR_IN6,ULONG,ULONG,
89 PSOCKADDR_IN6_PAIR*,ULONG*);
90 static void (WINAPI *pFreeMibTable)(void*);
91 static DWORD (WINAPI *pConvertInterfaceGuidToLuid)(const GUID*,NET_LUID*);
92 static DWORD (WINAPI *pConvertInterfaceIndexToLuid)(NET_IFINDEX,NET_LUID*);
93 static DWORD (WINAPI *pConvertInterfaceLuidToGuid)(const NET_LUID*,GUID*);
94 static DWORD (WINAPI *pConvertInterfaceLuidToIndex)(const NET_LUID*,NET_IFINDEX*);
95 static DWORD (WINAPI *pConvertInterfaceLuidToNameW)(const NET_LUID*,WCHAR*,SIZE_T);
96 static DWORD (WINAPI *pConvertInterfaceLuidToNameA)(const NET_LUID*,char*,SIZE_T);
97 static DWORD (WINAPI *pConvertInterfaceNameToLuidA)(const char*,NET_LUID*);
98 static DWORD (WINAPI *pConvertInterfaceNameToLuidW)(const WCHAR*,NET_LUID*);
99 static DWORD (WINAPI *pConvertLengthToIpv4Mask)(ULONG,ULONG*);
101 static PCHAR (WINAPI *pif_indextoname)(NET_IFINDEX,PCHAR);
102 static NET_IFINDEX (WINAPI *pif_nametoindex)(const char*);
104 static void loadIPHlpApi(void)
106 hLibrary = LoadLibraryA("iphlpapi.dll");
107 if (hLibrary) {
108 pAllocateAndGetTcpExTableFromStack = (void *)GetProcAddress(hLibrary, "AllocateAndGetTcpExTableFromStack");
109 pGetNumberOfInterfaces = (void *)GetProcAddress(hLibrary, "GetNumberOfInterfaces");
110 pGetIpAddrTable = (void *)GetProcAddress(hLibrary, "GetIpAddrTable");
111 pGetIfEntry = (void *)GetProcAddress(hLibrary, "GetIfEntry");
112 pGetIfEntry2 = (void *)GetProcAddress(hLibrary, "GetIfEntry2");
113 pGetFriendlyIfIndex = (void *)GetProcAddress(hLibrary, "GetFriendlyIfIndex");
114 pGetIfTable = (void *)GetProcAddress(hLibrary, "GetIfTable");
115 pGetIfTable2 = (void *)GetProcAddress(hLibrary, "GetIfTable2");
116 pGetIfTable2Ex = (void *)GetProcAddress(hLibrary, "GetIfTable2Ex");
117 pGetIpForwardTable = (void *)GetProcAddress(hLibrary, "GetIpForwardTable");
118 pGetIpNetTable = (void *)GetProcAddress(hLibrary, "GetIpNetTable");
119 pGetInterfaceInfo = (void *)GetProcAddress(hLibrary, "GetInterfaceInfo");
120 pGetAdaptersInfo = (void *)GetProcAddress(hLibrary, "GetAdaptersInfo");
121 pGetNetworkParams = (void *)GetProcAddress(hLibrary, "GetNetworkParams");
122 pGetIcmpStatistics = (void *)GetProcAddress(hLibrary, "GetIcmpStatistics");
123 pGetIpStatistics = (void *)GetProcAddress(hLibrary, "GetIpStatistics");
124 pGetTcpStatistics = (void *)GetProcAddress(hLibrary, "GetTcpStatistics");
125 pGetUdpStatistics = (void *)GetProcAddress(hLibrary, "GetUdpStatistics");
126 pGetIcmpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetIcmpStatisticsEx");
127 pGetIpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetIpStatisticsEx");
128 pGetTcpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetTcpStatisticsEx");
129 pGetUdpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetUdpStatisticsEx");
130 pGetTcpTable = (void *)GetProcAddress(hLibrary, "GetTcpTable");
131 pGetUdpTable = (void *)GetProcAddress(hLibrary, "GetUdpTable");
132 pGetPerAdapterInfo = (void *)GetProcAddress(hLibrary, "GetPerAdapterInfo");
133 pGetAdaptersAddresses = (void *)GetProcAddress(hLibrary, "GetAdaptersAddresses");
134 pGetUnicastIpAddressEntry = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressEntry");
135 pGetUnicastIpAddressTable = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressTable");
136 pNotifyAddrChange = (void *)GetProcAddress(hLibrary, "NotifyAddrChange");
137 pCancelIPChangeNotify = (void *)GetProcAddress(hLibrary, "CancelIPChangeNotify");
138 pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable");
139 pGetExtendedUdpTable = (void *)GetProcAddress(hLibrary, "GetExtendedUdpTable");
140 pSetTcpEntry = (void *)GetProcAddress(hLibrary, "SetTcpEntry");
141 pIcmpCreateFile = (void *)GetProcAddress(hLibrary, "IcmpCreateFile");
142 pIcmpSendEcho = (void *)GetProcAddress(hLibrary, "IcmpSendEcho");
143 pCreateSortedAddressPairs = (void *)GetProcAddress(hLibrary, "CreateSortedAddressPairs");
144 pFreeMibTable = (void *)GetProcAddress(hLibrary, "FreeMibTable");
145 pConvertInterfaceGuidToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceGuidToLuid");
146 pConvertInterfaceIndexToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceIndexToLuid");
147 pConvertInterfaceLuidToGuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToGuid");
148 pConvertInterfaceLuidToIndex = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToIndex");
149 pConvertInterfaceLuidToNameA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameA");
150 pConvertInterfaceLuidToNameW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameW");
151 pConvertInterfaceNameToLuidA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidA");
152 pConvertInterfaceNameToLuidW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidW");
153 pConvertLengthToIpv4Mask = (void *)GetProcAddress(hLibrary, "ConvertLengthToIpv4Mask");
154 pif_indextoname = (void *)GetProcAddress(hLibrary, "if_indextoname");
155 pif_nametoindex = (void *)GetProcAddress(hLibrary, "if_nametoindex");
159 static void freeIPHlpApi(void)
161 FreeLibrary(hLibrary);
164 /* replacement for inet_ntoa */
165 static const char *ntoa( DWORD ip )
167 static char buffer[40];
169 ip = htonl(ip);
170 sprintf( buffer, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff );
171 return buffer;
175 still-to-be-tested 98-only functions:
176 GetUniDirectionalAdapterInfo
178 static void testWin98OnlyFunctions(void)
182 static void testGetNumberOfInterfaces(void)
184 if (pGetNumberOfInterfaces) {
185 DWORD apiReturn, numInterfaces;
187 /* Crashes on Vista */
188 if (0) {
189 apiReturn = pGetNumberOfInterfaces(NULL);
190 if (apiReturn == ERROR_NOT_SUPPORTED)
191 return;
192 ok(apiReturn == ERROR_INVALID_PARAMETER,
193 "GetNumberOfInterfaces(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
194 apiReturn);
197 apiReturn = pGetNumberOfInterfaces(&numInterfaces);
198 if (apiReturn == ERROR_NOT_SUPPORTED) {
199 skip("GetNumberOfInterfaces is not supported\n");
200 return;
202 ok(apiReturn == NO_ERROR,
203 "GetNumberOfInterfaces returned %d, expected 0\n", apiReturn);
207 static void testGetIfEntry(DWORD index)
209 if (pGetIfEntry) {
210 DWORD apiReturn;
211 MIB_IFROW row;
213 memset(&row, 0, sizeof(row));
214 apiReturn = pGetIfEntry(NULL);
215 if (apiReturn == ERROR_NOT_SUPPORTED) {
216 skip("GetIfEntry is not supported\n");
217 return;
219 ok(apiReturn == ERROR_INVALID_PARAMETER,
220 "GetIfEntry(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
221 apiReturn);
222 row.dwIndex = -1; /* hope that's always bogus! */
223 apiReturn = pGetIfEntry(&row);
224 ok(apiReturn == ERROR_INVALID_DATA ||
225 apiReturn == ERROR_FILE_NOT_FOUND /* Vista */,
226 "GetIfEntry(bogus row) returned %d, expected ERROR_INVALID_DATA or ERROR_FILE_NOT_FOUND\n",
227 apiReturn);
228 row.dwIndex = index;
229 apiReturn = pGetIfEntry(&row);
230 ok(apiReturn == NO_ERROR,
231 "GetIfEntry returned %d, expected NO_ERROR\n", apiReturn);
235 static void testGetIpAddrTable(void)
237 if (pGetIpAddrTable) {
238 DWORD apiReturn;
239 ULONG dwSize = 0;
241 apiReturn = pGetIpAddrTable(NULL, NULL, FALSE);
242 if (apiReturn == ERROR_NOT_SUPPORTED) {
243 skip("GetIpAddrTable is not supported\n");
244 return;
246 ok(apiReturn == ERROR_INVALID_PARAMETER,
247 "GetIpAddrTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
248 apiReturn);
249 apiReturn = pGetIpAddrTable(NULL, &dwSize, FALSE);
250 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
251 "GetIpAddrTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
252 apiReturn);
253 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
254 PMIB_IPADDRTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
256 apiReturn = pGetIpAddrTable(buf, &dwSize, FALSE);
257 ok(apiReturn == NO_ERROR,
258 "GetIpAddrTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
259 apiReturn);
260 if (apiReturn == NO_ERROR && buf->dwNumEntries)
262 int i;
263 testGetIfEntry(buf->table[0].dwIndex);
264 for (i = 0; i < buf->dwNumEntries; i++)
266 ok (buf->table[i].wType != 0, "Test[%d]: expected wType > 0\n", i);
267 trace("Entry[%d]: addr %s, dwIndex %u, wType 0x%x\n", i,
268 ntoa(buf->table[i].dwAddr), buf->table[i].dwIndex, buf->table[i].wType);
269 /* loopback must never be the first when more than one interface is found */
270 if (buf->table[i].dwAddr == htonl(INADDR_LOOPBACK))
271 ok(buf->dwNumEntries == 1 || i, "Loopback interface in wrong first position\n");
274 HeapFree(GetProcessHeap(), 0, buf);
279 static void testGetIfTable(void)
281 if (pGetIfTable) {
282 DWORD apiReturn;
283 ULONG dwSize = 0;
285 apiReturn = pGetIfTable(NULL, NULL, FALSE);
286 if (apiReturn == ERROR_NOT_SUPPORTED) {
287 skip("GetIfTable is not supported\n");
288 return;
290 ok(apiReturn == ERROR_INVALID_PARAMETER,
291 "GetIfTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
292 apiReturn);
293 apiReturn = pGetIfTable(NULL, &dwSize, FALSE);
294 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
295 "GetIfTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
296 apiReturn);
297 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
298 PMIB_IFTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
300 apiReturn = pGetIfTable(buf, &dwSize, FALSE);
301 ok(apiReturn == NO_ERROR,
302 "GetIfTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n\n",
303 apiReturn);
305 if (apiReturn == NO_ERROR && winetest_debug > 1)
307 DWORD i, j;
308 char name[MAX_INTERFACE_NAME_LEN];
310 trace( "interface table: %u entries\n", buf->dwNumEntries );
311 for (i = 0; i < buf->dwNumEntries; i++)
313 MIB_IFROW *row = &buf->table[i];
314 WideCharToMultiByte( CP_ACP, 0, row->wszName, -1, name, MAX_INTERFACE_NAME_LEN, NULL, NULL );
315 trace( "%u: '%s' type %u mtu %u speed %u phys",
316 row->dwIndex, name, row->dwType, row->dwMtu, row->dwSpeed );
317 for (j = 0; j < row->dwPhysAddrLen; j++)
318 printf( " %02x", row->bPhysAddr[j] );
319 printf( "\n" );
320 trace( " in: bytes %u upkts %u nupkts %u disc %u err %u unk %u\n",
321 row->dwInOctets, row->dwInUcastPkts, row->dwInNUcastPkts,
322 row->dwInDiscards, row->dwInErrors, row->dwInUnknownProtos );
323 trace( " out: bytes %u upkts %u nupkts %u disc %u err %u\n",
324 row->dwOutOctets, row->dwOutUcastPkts, row->dwOutNUcastPkts,
325 row->dwOutDiscards, row->dwOutErrors );
328 HeapFree(GetProcessHeap(), 0, buf);
333 static void testGetIpForwardTable(void)
335 if (pGetIpForwardTable) {
336 DWORD apiReturn;
337 ULONG dwSize = 0;
339 apiReturn = pGetIpForwardTable(NULL, NULL, FALSE);
340 if (apiReturn == ERROR_NOT_SUPPORTED) {
341 skip("GetIpForwardTable is not supported\n");
342 return;
344 ok(apiReturn == ERROR_INVALID_PARAMETER,
345 "GetIpForwardTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
346 apiReturn);
347 apiReturn = pGetIpForwardTable(NULL, &dwSize, FALSE);
348 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
349 "GetIpForwardTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
350 apiReturn);
351 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
352 PMIB_IPFORWARDTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
354 apiReturn = pGetIpForwardTable(buf, &dwSize, FALSE);
355 ok(apiReturn == NO_ERROR,
356 "GetIpForwardTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
357 apiReturn);
359 if (apiReturn == NO_ERROR)
361 DWORD i;
363 trace( "IP forward table: %u entries\n", buf->dwNumEntries );
364 for (i = 0; i < buf->dwNumEntries; i++)
366 char buffer[100];
368 if (!U1(buf->table[i]).dwForwardDest) /* Default route */
370 todo_wine
371 ok (U1(buf->table[i]).dwForwardProto == MIB_IPPROTO_NETMGMT,
372 "Unexpected dwForwardProto %d\n", U1(buf->table[i]).dwForwardProto);
373 ok (U1(buf->table[i]).dwForwardType == MIB_IPROUTE_TYPE_INDIRECT,
374 "Unexpected dwForwardType %d\n", U1(buf->table[i]).dwForwardType);
376 else
378 /* In general we should get MIB_IPPROTO_LOCAL but does not work
379 * for Vista, 2008 and 7. */
380 ok (U1(buf->table[i]).dwForwardProto == MIB_IPPROTO_LOCAL ||
381 broken(U1(buf->table[i]).dwForwardProto == MIB_IPPROTO_NETMGMT),
382 "Unexpected dwForwardProto %d\n", U1(buf->table[i]).dwForwardProto);
383 /* The forward type varies depending on the address and gateway
384 * value so it is not worth testing in this case. */
387 sprintf( buffer, "dest %s", ntoa( buf->table[i].dwForwardDest ));
388 sprintf( buffer + strlen(buffer), " mask %s", ntoa( buf->table[i].dwForwardMask ));
389 trace( "%u: %s gw %s if %u type %u proto %u\n", i, buffer,
390 ntoa( buf->table[i].dwForwardNextHop ), buf->table[i].dwForwardIfIndex,
391 U1(buf->table[i]).dwForwardType, U1(buf->table[i]).dwForwardProto );
394 HeapFree(GetProcessHeap(), 0, buf);
399 static void testGetIpNetTable(void)
401 if (pGetIpNetTable) {
402 DWORD apiReturn;
403 ULONG dwSize = 0;
405 apiReturn = pGetIpNetTable(NULL, NULL, FALSE);
406 if (apiReturn == ERROR_NOT_SUPPORTED) {
407 skip("GetIpNetTable is not supported\n");
408 return;
410 ok(apiReturn == ERROR_INVALID_PARAMETER,
411 "GetIpNetTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
412 apiReturn);
413 apiReturn = pGetIpNetTable(NULL, &dwSize, FALSE);
414 ok(apiReturn == ERROR_NO_DATA || apiReturn == ERROR_INSUFFICIENT_BUFFER,
415 "GetIpNetTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_NO_DATA or ERROR_INSUFFICIENT_BUFFER\n",
416 apiReturn);
417 if (apiReturn == ERROR_NO_DATA)
418 ; /* empty ARP table's okay */
419 else if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
420 PMIB_IPNETTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
422 apiReturn = pGetIpNetTable(buf, &dwSize, FALSE);
423 ok(apiReturn == NO_ERROR ||
424 apiReturn == ERROR_NO_DATA, /* empty ARP table's okay */
425 "GetIpNetTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
426 apiReturn);
428 if (apiReturn == NO_ERROR && winetest_debug > 1)
430 DWORD i, j;
432 trace( "IP net table: %u entries\n", buf->dwNumEntries );
433 for (i = 0; i < buf->dwNumEntries; i++)
435 trace( "%u: idx %u type %u addr %s phys",
436 i, buf->table[i].dwIndex, U(buf->table[i]).dwType, ntoa( buf->table[i].dwAddr ));
437 for (j = 0; j < buf->table[i].dwPhysAddrLen; j++)
438 printf( " %02x", buf->table[i].bPhysAddr[j] );
439 printf( "\n" );
442 HeapFree(GetProcessHeap(), 0, buf);
447 static void testGetIcmpStatistics(void)
449 if (pGetIcmpStatistics) {
450 DWORD apiReturn;
451 MIB_ICMP stats;
453 /* Crashes on Vista */
454 if (0) {
455 apiReturn = pGetIcmpStatistics(NULL);
456 if (apiReturn == ERROR_NOT_SUPPORTED)
457 return;
458 ok(apiReturn == ERROR_INVALID_PARAMETER,
459 "GetIcmpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
460 apiReturn);
463 apiReturn = pGetIcmpStatistics(&stats);
464 if (apiReturn == ERROR_NOT_SUPPORTED)
466 skip("GetIcmpStatistics is not supported\n");
467 return;
469 ok(apiReturn == NO_ERROR,
470 "GetIcmpStatistics returned %d, expected NO_ERROR\n", apiReturn);
471 if (apiReturn == NO_ERROR && winetest_debug > 1)
473 trace( "ICMP stats: %8s %8s\n", "in", "out" );
474 trace( " dwMsgs: %8u %8u\n", stats.stats.icmpInStats.dwMsgs, stats.stats.icmpOutStats.dwMsgs );
475 trace( " dwErrors: %8u %8u\n", stats.stats.icmpInStats.dwErrors, stats.stats.icmpOutStats.dwErrors );
476 trace( " dwDestUnreachs: %8u %8u\n", stats.stats.icmpInStats.dwDestUnreachs, stats.stats.icmpOutStats.dwDestUnreachs );
477 trace( " dwTimeExcds: %8u %8u\n", stats.stats.icmpInStats.dwTimeExcds, stats.stats.icmpOutStats.dwTimeExcds );
478 trace( " dwParmProbs: %8u %8u\n", stats.stats.icmpInStats.dwParmProbs, stats.stats.icmpOutStats.dwParmProbs );
479 trace( " dwSrcQuenchs: %8u %8u\n", stats.stats.icmpInStats.dwSrcQuenchs, stats.stats.icmpOutStats.dwSrcQuenchs );
480 trace( " dwRedirects: %8u %8u\n", stats.stats.icmpInStats.dwRedirects, stats.stats.icmpOutStats.dwRedirects );
481 trace( " dwEchos: %8u %8u\n", stats.stats.icmpInStats.dwEchos, stats.stats.icmpOutStats.dwEchos );
482 trace( " dwEchoReps: %8u %8u\n", stats.stats.icmpInStats.dwEchoReps, stats.stats.icmpOutStats.dwEchoReps );
483 trace( " dwTimestamps: %8u %8u\n", stats.stats.icmpInStats.dwTimestamps, stats.stats.icmpOutStats.dwTimestamps );
484 trace( " dwTimestampReps: %8u %8u\n", stats.stats.icmpInStats.dwTimestampReps, stats.stats.icmpOutStats.dwTimestampReps );
485 trace( " dwAddrMasks: %8u %8u\n", stats.stats.icmpInStats.dwAddrMasks, stats.stats.icmpOutStats.dwAddrMasks );
486 trace( " dwAddrMaskReps: %8u %8u\n", stats.stats.icmpInStats.dwAddrMaskReps, stats.stats.icmpOutStats.dwAddrMaskReps );
491 static void testGetIpStatistics(void)
493 if (pGetIpStatistics) {
494 DWORD apiReturn;
495 MIB_IPSTATS stats;
497 apiReturn = pGetIpStatistics(NULL);
498 if (apiReturn == ERROR_NOT_SUPPORTED) {
499 skip("GetIpStatistics is not supported\n");
500 return;
502 ok(apiReturn == ERROR_INVALID_PARAMETER,
503 "GetIpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
504 apiReturn);
505 apiReturn = pGetIpStatistics(&stats);
506 ok(apiReturn == NO_ERROR,
507 "GetIpStatistics returned %d, expected NO_ERROR\n", apiReturn);
508 if (apiReturn == NO_ERROR && winetest_debug > 1)
510 trace( "IP stats:\n" );
511 trace( " dwForwarding: %u\n", U(stats).dwForwarding );
512 trace( " dwDefaultTTL: %u\n", stats.dwDefaultTTL );
513 trace( " dwInReceives: %u\n", stats.dwInReceives );
514 trace( " dwInHdrErrors: %u\n", stats.dwInHdrErrors );
515 trace( " dwInAddrErrors: %u\n", stats.dwInAddrErrors );
516 trace( " dwForwDatagrams: %u\n", stats.dwForwDatagrams );
517 trace( " dwInUnknownProtos: %u\n", stats.dwInUnknownProtos );
518 trace( " dwInDiscards: %u\n", stats.dwInDiscards );
519 trace( " dwInDelivers: %u\n", stats.dwInDelivers );
520 trace( " dwOutRequests: %u\n", stats.dwOutRequests );
521 trace( " dwRoutingDiscards: %u\n", stats.dwRoutingDiscards );
522 trace( " dwOutDiscards: %u\n", stats.dwOutDiscards );
523 trace( " dwOutNoRoutes: %u\n", stats.dwOutNoRoutes );
524 trace( " dwReasmTimeout: %u\n", stats.dwReasmTimeout );
525 trace( " dwReasmReqds: %u\n", stats.dwReasmReqds );
526 trace( " dwReasmOks: %u\n", stats.dwReasmOks );
527 trace( " dwReasmFails: %u\n", stats.dwReasmFails );
528 trace( " dwFragOks: %u\n", stats.dwFragOks );
529 trace( " dwFragFails: %u\n", stats.dwFragFails );
530 trace( " dwFragCreates: %u\n", stats.dwFragCreates );
531 trace( " dwNumIf: %u\n", stats.dwNumIf );
532 trace( " dwNumAddr: %u\n", stats.dwNumAddr );
533 trace( " dwNumRoutes: %u\n", stats.dwNumRoutes );
538 static void testGetTcpStatistics(void)
540 if (pGetTcpStatistics) {
541 DWORD apiReturn;
542 MIB_TCPSTATS stats;
544 apiReturn = pGetTcpStatistics(NULL);
545 if (apiReturn == ERROR_NOT_SUPPORTED) {
546 skip("GetTcpStatistics is not supported\n");
547 return;
549 ok(apiReturn == ERROR_INVALID_PARAMETER,
550 "GetTcpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
551 apiReturn);
552 apiReturn = pGetTcpStatistics(&stats);
553 ok(apiReturn == NO_ERROR,
554 "GetTcpStatistics returned %d, expected NO_ERROR\n", apiReturn);
555 if (apiReturn == NO_ERROR && winetest_debug > 1)
557 trace( "TCP stats:\n" );
558 trace( " dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
559 trace( " dwRtoMin: %u\n", stats.dwRtoMin );
560 trace( " dwRtoMax: %u\n", stats.dwRtoMax );
561 trace( " dwMaxConn: %u\n", stats.dwMaxConn );
562 trace( " dwActiveOpens: %u\n", stats.dwActiveOpens );
563 trace( " dwPassiveOpens: %u\n", stats.dwPassiveOpens );
564 trace( " dwAttemptFails: %u\n", stats.dwAttemptFails );
565 trace( " dwEstabResets: %u\n", stats.dwEstabResets );
566 trace( " dwCurrEstab: %u\n", stats.dwCurrEstab );
567 trace( " dwInSegs: %u\n", stats.dwInSegs );
568 trace( " dwOutSegs: %u\n", stats.dwOutSegs );
569 trace( " dwRetransSegs: %u\n", stats.dwRetransSegs );
570 trace( " dwInErrs: %u\n", stats.dwInErrs );
571 trace( " dwOutRsts: %u\n", stats.dwOutRsts );
572 trace( " dwNumConns: %u\n", stats.dwNumConns );
577 static void testGetUdpStatistics(void)
579 if (pGetUdpStatistics) {
580 DWORD apiReturn;
581 MIB_UDPSTATS stats;
583 apiReturn = pGetUdpStatistics(NULL);
584 if (apiReturn == ERROR_NOT_SUPPORTED) {
585 skip("GetUdpStatistics is not supported\n");
586 return;
588 ok(apiReturn == ERROR_INVALID_PARAMETER,
589 "GetUdpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
590 apiReturn);
591 apiReturn = pGetUdpStatistics(&stats);
592 ok(apiReturn == NO_ERROR,
593 "GetUdpStatistics returned %d, expected NO_ERROR\n", apiReturn);
594 if (apiReturn == NO_ERROR && winetest_debug > 1)
596 trace( "UDP stats:\n" );
597 trace( " dwInDatagrams: %u\n", stats.dwInDatagrams );
598 trace( " dwNoPorts: %u\n", stats.dwNoPorts );
599 trace( " dwInErrors: %u\n", stats.dwInErrors );
600 trace( " dwOutDatagrams: %u\n", stats.dwOutDatagrams );
601 trace( " dwNumAddrs: %u\n", stats.dwNumAddrs );
606 static void testGetIcmpStatisticsEx(void)
608 DWORD apiReturn;
609 MIB_ICMP_EX stats;
611 if (!pGetIcmpStatisticsEx)
613 win_skip( "GetIcmpStatisticsEx not available\n" );
614 return;
617 /* Crashes on Vista */
618 if (1) {
619 apiReturn = pGetIcmpStatisticsEx(NULL, AF_INET);
620 ok(apiReturn == ERROR_INVALID_PARAMETER,
621 "GetIcmpStatisticsEx(NULL, AF_INET) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
624 apiReturn = pGetIcmpStatisticsEx(&stats, AF_BAN);
625 ok(apiReturn == ERROR_INVALID_PARAMETER,
626 "GetIcmpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
628 apiReturn = pGetIcmpStatisticsEx(&stats, AF_INET);
629 ok(apiReturn == NO_ERROR, "GetIcmpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
630 if (apiReturn == NO_ERROR && winetest_debug > 1)
632 INT i;
633 trace( "ICMP IPv4 Ex stats: %8s %8s\n", "in", "out" );
634 trace( " dwMsgs: %8u %8u\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
635 trace( " dwErrors: %8u %8u\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
636 for (i = 0; i < 256; i++)
637 trace( " rgdwTypeCount[%3i]: %8u %8u\n", i, stats.icmpInStats.rgdwTypeCount[i], stats.icmpOutStats.rgdwTypeCount[i] );
640 apiReturn = pGetIcmpStatisticsEx(&stats, AF_INET6);
641 ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
642 "GetIcmpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
643 if (apiReturn == NO_ERROR && winetest_debug > 1)
645 INT i;
646 trace( "ICMP IPv6 Ex stats: %8s %8s\n", "in", "out" );
647 trace( " dwMsgs: %8u %8u\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
648 trace( " dwErrors: %8u %8u\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
649 for (i = 0; i < 256; i++)
650 trace( " rgdwTypeCount[%3i]: %8u %8u\n", i, stats.icmpInStats.rgdwTypeCount[i], stats.icmpOutStats.rgdwTypeCount[i] );
654 static void testGetIpStatisticsEx(void)
656 DWORD apiReturn;
657 MIB_IPSTATS stats;
659 if (!pGetIpStatisticsEx)
661 win_skip( "GetIpStatisticsEx not available\n" );
662 return;
665 apiReturn = pGetIpStatisticsEx(NULL, AF_INET);
666 ok(apiReturn == ERROR_INVALID_PARAMETER,
667 "GetIpStatisticsEx(NULL, AF_INET) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
669 apiReturn = pGetIpStatisticsEx(&stats, AF_BAN);
670 ok(apiReturn == ERROR_INVALID_PARAMETER,
671 "GetIpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
673 apiReturn = pGetIpStatisticsEx(&stats, AF_INET);
674 ok(apiReturn == NO_ERROR, "GetIpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
675 if (apiReturn == NO_ERROR && winetest_debug > 1)
677 trace( "IP IPv4 Ex stats:\n" );
678 trace( " dwForwarding: %u\n", U(stats).dwForwarding );
679 trace( " dwDefaultTTL: %u\n", stats.dwDefaultTTL );
680 trace( " dwInReceives: %u\n", stats.dwInReceives );
681 trace( " dwInHdrErrors: %u\n", stats.dwInHdrErrors );
682 trace( " dwInAddrErrors: %u\n", stats.dwInAddrErrors );
683 trace( " dwForwDatagrams: %u\n", stats.dwForwDatagrams );
684 trace( " dwInUnknownProtos: %u\n", stats.dwInUnknownProtos );
685 trace( " dwInDiscards: %u\n", stats.dwInDiscards );
686 trace( " dwInDelivers: %u\n", stats.dwInDelivers );
687 trace( " dwOutRequests: %u\n", stats.dwOutRequests );
688 trace( " dwRoutingDiscards: %u\n", stats.dwRoutingDiscards );
689 trace( " dwOutDiscards: %u\n", stats.dwOutDiscards );
690 trace( " dwOutNoRoutes: %u\n", stats.dwOutNoRoutes );
691 trace( " dwReasmTimeout: %u\n", stats.dwReasmTimeout );
692 trace( " dwReasmReqds: %u\n", stats.dwReasmReqds );
693 trace( " dwReasmOks: %u\n", stats.dwReasmOks );
694 trace( " dwReasmFails: %u\n", stats.dwReasmFails );
695 trace( " dwFragOks: %u\n", stats.dwFragOks );
696 trace( " dwFragFails: %u\n", stats.dwFragFails );
697 trace( " dwFragCreates: %u\n", stats.dwFragCreates );
698 trace( " dwNumIf: %u\n", stats.dwNumIf );
699 trace( " dwNumAddr: %u\n", stats.dwNumAddr );
700 trace( " dwNumRoutes: %u\n", stats.dwNumRoutes );
703 apiReturn = pGetIpStatisticsEx(&stats, AF_INET6);
704 ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
705 "GetIpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
706 if (apiReturn == NO_ERROR && winetest_debug > 1)
708 trace( "IP IPv6 Ex stats:\n" );
709 trace( " dwForwarding: %u\n", U(stats).dwForwarding );
710 trace( " dwDefaultTTL: %u\n", stats.dwDefaultTTL );
711 trace( " dwInReceives: %u\n", stats.dwInReceives );
712 trace( " dwInHdrErrors: %u\n", stats.dwInHdrErrors );
713 trace( " dwInAddrErrors: %u\n", stats.dwInAddrErrors );
714 trace( " dwForwDatagrams: %u\n", stats.dwForwDatagrams );
715 trace( " dwInUnknownProtos: %u\n", stats.dwInUnknownProtos );
716 trace( " dwInDiscards: %u\n", stats.dwInDiscards );
717 trace( " dwInDelivers: %u\n", stats.dwInDelivers );
718 trace( " dwOutRequests: %u\n", stats.dwOutRequests );
719 trace( " dwRoutingDiscards: %u\n", stats.dwRoutingDiscards );
720 trace( " dwOutDiscards: %u\n", stats.dwOutDiscards );
721 trace( " dwOutNoRoutes: %u\n", stats.dwOutNoRoutes );
722 trace( " dwReasmTimeout: %u\n", stats.dwReasmTimeout );
723 trace( " dwReasmReqds: %u\n", stats.dwReasmReqds );
724 trace( " dwReasmOks: %u\n", stats.dwReasmOks );
725 trace( " dwReasmFails: %u\n", stats.dwReasmFails );
726 trace( " dwFragOks: %u\n", stats.dwFragOks );
727 trace( " dwFragFails: %u\n", stats.dwFragFails );
728 trace( " dwFragCreates: %u\n", stats.dwFragCreates );
729 trace( " dwNumIf: %u\n", stats.dwNumIf );
730 trace( " dwNumAddr: %u\n", stats.dwNumAddr );
731 trace( " dwNumRoutes: %u\n", stats.dwNumRoutes );
735 static void testGetTcpStatisticsEx(void)
737 DWORD apiReturn;
738 MIB_TCPSTATS stats;
740 if (!pGetTcpStatisticsEx)
742 win_skip( "GetTcpStatisticsEx not available\n" );
743 return;
746 apiReturn = pGetTcpStatisticsEx(NULL, AF_INET);
747 ok(apiReturn == ERROR_INVALID_PARAMETER,
748 "GetTcpStatisticsEx(NULL, AF_INET); returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
750 apiReturn = pGetTcpStatisticsEx(&stats, AF_BAN);
751 ok(apiReturn == ERROR_INVALID_PARAMETER || apiReturn == ERROR_NOT_SUPPORTED,
752 "GetTcpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
754 apiReturn = pGetTcpStatisticsEx(&stats, AF_INET);
755 ok(apiReturn == NO_ERROR, "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
756 if (apiReturn == NO_ERROR && winetest_debug > 1)
758 trace( "TCP IPv4 Ex stats:\n" );
759 trace( " dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
760 trace( " dwRtoMin: %u\n", stats.dwRtoMin );
761 trace( " dwRtoMax: %u\n", stats.dwRtoMax );
762 trace( " dwMaxConn: %u\n", stats.dwMaxConn );
763 trace( " dwActiveOpens: %u\n", stats.dwActiveOpens );
764 trace( " dwPassiveOpens: %u\n", stats.dwPassiveOpens );
765 trace( " dwAttemptFails: %u\n", stats.dwAttemptFails );
766 trace( " dwEstabResets: %u\n", stats.dwEstabResets );
767 trace( " dwCurrEstab: %u\n", stats.dwCurrEstab );
768 trace( " dwInSegs: %u\n", stats.dwInSegs );
769 trace( " dwOutSegs: %u\n", stats.dwOutSegs );
770 trace( " dwRetransSegs: %u\n", stats.dwRetransSegs );
771 trace( " dwInErrs: %u\n", stats.dwInErrs );
772 trace( " dwOutRsts: %u\n", stats.dwOutRsts );
773 trace( " dwNumConns: %u\n", stats.dwNumConns );
776 apiReturn = pGetTcpStatisticsEx(&stats, AF_INET6);
777 todo_wine ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
778 "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
779 if (apiReturn == NO_ERROR && winetest_debug > 1)
781 trace( "TCP IPv6 Ex stats:\n" );
782 trace( " dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
783 trace( " dwRtoMin: %u\n", stats.dwRtoMin );
784 trace( " dwRtoMax: %u\n", stats.dwRtoMax );
785 trace( " dwMaxConn: %u\n", stats.dwMaxConn );
786 trace( " dwActiveOpens: %u\n", stats.dwActiveOpens );
787 trace( " dwPassiveOpens: %u\n", stats.dwPassiveOpens );
788 trace( " dwAttemptFails: %u\n", stats.dwAttemptFails );
789 trace( " dwEstabResets: %u\n", stats.dwEstabResets );
790 trace( " dwCurrEstab: %u\n", stats.dwCurrEstab );
791 trace( " dwInSegs: %u\n", stats.dwInSegs );
792 trace( " dwOutSegs: %u\n", stats.dwOutSegs );
793 trace( " dwRetransSegs: %u\n", stats.dwRetransSegs );
794 trace( " dwInErrs: %u\n", stats.dwInErrs );
795 trace( " dwOutRsts: %u\n", stats.dwOutRsts );
796 trace( " dwNumConns: %u\n", stats.dwNumConns );
800 static void testGetUdpStatisticsEx(void)
802 DWORD apiReturn;
803 MIB_UDPSTATS stats;
805 if (!pGetUdpStatisticsEx)
807 win_skip( "GetUdpStatisticsEx not available\n" );
808 return;
811 apiReturn = pGetUdpStatisticsEx(NULL, AF_INET);
812 ok(apiReturn == ERROR_INVALID_PARAMETER,
813 "GetUdpStatisticsEx(NULL, AF_INET); returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
815 apiReturn = pGetUdpStatisticsEx(&stats, AF_BAN);
816 ok(apiReturn == ERROR_INVALID_PARAMETER || apiReturn == ERROR_NOT_SUPPORTED,
817 "GetUdpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
819 apiReturn = pGetUdpStatisticsEx(&stats, AF_INET);
820 ok(apiReturn == NO_ERROR, "GetUdpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
821 if (apiReturn == NO_ERROR && winetest_debug > 1)
823 trace( "UDP IPv4 Ex stats:\n" );
824 trace( " dwInDatagrams: %u\n", stats.dwInDatagrams );
825 trace( " dwNoPorts: %u\n", stats.dwNoPorts );
826 trace( " dwInErrors: %u\n", stats.dwInErrors );
827 trace( " dwOutDatagrams: %u\n", stats.dwOutDatagrams );
828 trace( " dwNumAddrs: %u\n", stats.dwNumAddrs );
831 apiReturn = pGetUdpStatisticsEx(&stats, AF_INET6);
832 ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
833 "GetUdpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
834 if (apiReturn == NO_ERROR && winetest_debug > 1)
836 trace( "UDP IPv6 Ex stats:\n" );
837 trace( " dwInDatagrams: %u\n", stats.dwInDatagrams );
838 trace( " dwNoPorts: %u\n", stats.dwNoPorts );
839 trace( " dwInErrors: %u\n", stats.dwInErrors );
840 trace( " dwOutDatagrams: %u\n", stats.dwOutDatagrams );
841 trace( " dwNumAddrs: %u\n", stats.dwNumAddrs );
845 static void testGetTcpTable(void)
847 if (pGetTcpTable) {
848 DWORD apiReturn;
849 ULONG dwSize = 0;
851 apiReturn = pGetTcpTable(NULL, &dwSize, FALSE);
852 if (apiReturn == ERROR_NOT_SUPPORTED) {
853 skip("GetTcpTable is not supported\n");
854 return;
856 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER ||
857 broken(apiReturn == ERROR_NO_DATA), /* win95 */
858 "GetTcpTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
859 apiReturn);
860 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
861 PMIB_TCPTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
863 apiReturn = pGetTcpTable(buf, &dwSize, FALSE);
864 ok(apiReturn == NO_ERROR,
865 "GetTcpTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
866 apiReturn);
868 if (apiReturn == NO_ERROR && winetest_debug > 1)
870 DWORD i;
871 trace( "TCP table: %u entries\n", buf->dwNumEntries );
872 for (i = 0; i < buf->dwNumEntries; i++)
874 char buffer[40];
875 sprintf( buffer, "local %s:%u",
876 ntoa(buf->table[i].dwLocalAddr), ntohs(buf->table[i].dwLocalPort) );
877 trace( "%u: %s remote %s:%u state %u\n",
878 i, buffer, ntoa( buf->table[i].dwRemoteAddr ),
879 ntohs(buf->table[i].dwRemotePort), U(buf->table[i]).dwState );
882 HeapFree(GetProcessHeap(), 0, buf);
887 static void testGetUdpTable(void)
889 if (pGetUdpTable) {
890 DWORD apiReturn;
891 ULONG dwSize = 0;
893 apiReturn = pGetUdpTable(NULL, &dwSize, FALSE);
894 if (apiReturn == ERROR_NOT_SUPPORTED) {
895 skip("GetUdpTable is not supported\n");
896 return;
898 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
899 "GetUdpTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
900 apiReturn);
901 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
902 PMIB_UDPTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
904 apiReturn = pGetUdpTable(buf, &dwSize, FALSE);
905 ok(apiReturn == NO_ERROR,
906 "GetUdpTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
907 apiReturn);
909 if (apiReturn == NO_ERROR && winetest_debug > 1)
911 DWORD i;
912 trace( "UDP table: %u entries\n", buf->dwNumEntries );
913 for (i = 0; i < buf->dwNumEntries; i++)
914 trace( "%u: %s:%u\n",
915 i, ntoa( buf->table[i].dwLocalAddr ), ntohs(buf->table[i].dwLocalPort) );
917 HeapFree(GetProcessHeap(), 0, buf);
922 static void testSetTcpEntry(void)
924 DWORD ret;
925 MIB_TCPROW row;
927 memset(&row, 0, sizeof(row));
928 if(0) /* This test crashes in OS >= VISTA */
930 ret = pSetTcpEntry(NULL);
931 ok( ret == ERROR_INVALID_PARAMETER, "got %u, expected %u\n", ret, ERROR_INVALID_PARAMETER);
934 ret = pSetTcpEntry(&row);
935 if (ret == ERROR_NETWORK_ACCESS_DENIED)
937 win_skip("SetTcpEntry failed with access error. Skipping test.\n");
938 return;
940 todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %u, expected %u\n", ret, ERROR_INVALID_PARAMETER);
942 U(row).dwState = MIB_TCP_STATE_DELETE_TCB;
943 ret = pSetTcpEntry(&row);
944 todo_wine ok( ret == ERROR_MR_MID_NOT_FOUND || broken(ret == ERROR_INVALID_PARAMETER),
945 "got %u, expected %u\n", ret, ERROR_MR_MID_NOT_FOUND);
948 static void testIcmpSendEcho(void)
950 HANDLE icmp;
951 char senddata[32], replydata[sizeof(senddata) + sizeof(ICMP_ECHO_REPLY)];
952 DWORD ret, error, replysz = sizeof(replydata);
953 IPAddr address;
954 ICMP_ECHO_REPLY *reply;
955 INT i;
957 if (!pIcmpSendEcho || !pIcmpCreateFile)
959 win_skip( "IcmpSendEcho or IcmpCreateFile not available\n" );
960 return;
962 memset(senddata, 0, sizeof(senddata));
964 address = htonl(INADDR_LOOPBACK);
965 SetLastError(0xdeadbeef);
966 ret = pIcmpSendEcho(INVALID_HANDLE_VALUE, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
967 error = GetLastError();
968 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
969 todo_wine
970 ok (error == ERROR_INVALID_PARAMETER
971 || broken(error == ERROR_INVALID_HANDLE) /* <= 2003 */,
972 "expected 87, got %d\n", error);
974 icmp = pIcmpCreateFile();
975 if (icmp == INVALID_HANDLE_VALUE)
977 error = GetLastError();
978 if (error == ERROR_ACCESS_DENIED)
980 skip ("ICMP is not available.\n");
981 return;
984 ok (icmp != INVALID_HANDLE_VALUE, "IcmpCreateFile failed unexpectedly with error %d\n", GetLastError());
986 address = 0;
987 SetLastError(0xdeadbeef);
988 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
989 error = GetLastError();
990 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
991 ok (error == ERROR_INVALID_NETNAME
992 || broken(error == IP_BAD_DESTINATION) /* <= 2003 */,
993 "expected 1214, got %d\n", error);
995 address = htonl(INADDR_LOOPBACK);
996 if (0) /* crashes in XP */
998 ret = pIcmpSendEcho(icmp, address, NULL, sizeof(senddata), NULL, replydata, replysz, 1000);
999 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1002 SetLastError(0xdeadbeef);
1003 ret = pIcmpSendEcho(icmp, address, senddata, 0, NULL, replydata, replysz, 1000);
1004 error = GetLastError();
1005 ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
1007 SetLastError(0xdeadbeef);
1008 ret = pIcmpSendEcho(icmp, address, NULL, 0, NULL, replydata, replysz, 1000);
1009 error = GetLastError();
1010 ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
1012 if (0) /* crashes in wine, remove IF when fixed */
1014 SetLastError(0xdeadbeef);
1015 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, NULL, replysz, 1000);
1016 error = GetLastError();
1017 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1018 ok (error == ERROR_INVALID_PARAMETER, "expected 87, got %d\n", error);
1021 SetLastError(0xdeadbeef);
1022 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, 0, 1000);
1023 error = GetLastError();
1024 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1025 todo_wine
1026 ok (error == ERROR_INVALID_PARAMETER
1027 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1028 "expected 87, got %d\n", error);
1030 SetLastError(0xdeadbeef);
1031 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, NULL, 0, 1000);
1032 error = GetLastError();
1033 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1034 todo_wine
1035 ok (error == ERROR_INVALID_PARAMETER
1036 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1037 "expected 87, got %d\n", error);
1039 SetLastError(0xdeadbeef);
1040 replysz = sizeof(replydata) - 1;
1041 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1042 error = GetLastError();
1043 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1044 ok (error == IP_GENERAL_FAILURE
1045 || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1046 "expected 11050, got %d\n", error);
1048 SetLastError(0xdeadbeef);
1049 replysz = sizeof(ICMP_ECHO_REPLY);
1050 ret = pIcmpSendEcho(icmp, address, senddata, 0, NULL, replydata, replysz, 1000);
1051 error = GetLastError();
1052 todo_wine
1053 ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
1055 SetLastError(0xdeadbeef);
1056 replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
1057 ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz, 1000);
1058 error = GetLastError();
1059 ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
1061 SetLastError(0xdeadbeef);
1062 replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
1063 ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN + 1, NULL, replydata, replysz, 1000);
1064 error = GetLastError();
1065 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1066 ok (error == IP_GENERAL_FAILURE
1067 || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1068 "expected 11050, got %d\n", error);
1070 SetLastError(0xdeadbeef);
1071 ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz - 1, 1000);
1072 error = GetLastError();
1073 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1074 todo_wine
1075 ok (error == IP_GENERAL_FAILURE
1076 || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1077 "expected 11050, got %d\n", error);
1079 /* in windows >= vista the timeout can't be invalid */
1080 SetLastError(0xdeadbeef);
1081 replysz = sizeof(replydata);
1082 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 0);
1083 error = GetLastError();
1084 if (!ret) ok(error == ERROR_INVALID_PARAMETER, "expected 87, got %d\n", error);
1086 SetLastError(0xdeadbeef);
1087 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, -1);
1088 error = GetLastError();
1089 if (!ret) ok(error == ERROR_INVALID_PARAMETER, "expected 87, got %d\n", error);
1091 /* real ping test */
1092 SetLastError(0xdeadbeef);
1093 address = htonl(INADDR_LOOPBACK);
1094 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1095 error = GetLastError();
1096 if (ret)
1098 PICMP_ECHO_REPLY pong = (PICMP_ECHO_REPLY) replydata;
1099 trace ("send addr : %s\n", ntoa(address));
1100 trace ("reply addr : %s\n", ntoa(pong->Address));
1101 trace ("reply size : %u\n", replysz);
1102 trace ("roundtrip : %u ms\n", pong->RoundTripTime);
1103 trace ("status : %u\n", pong->Status);
1104 trace ("recv size : %u\n", pong->DataSize);
1105 trace ("ttl : %u\n", pong->Options.Ttl);
1106 trace ("flags : 0x%x\n", pong->Options.Flags);
1108 else
1110 skip ("Failed to ping with error %d, is lo interface down?.\n", error);
1113 /* check reply data */
1114 SetLastError(0xdeadbeef);
1115 address = htonl(INADDR_LOOPBACK);
1116 for (i = 0; i < ARRAY_SIZE(senddata); i++) senddata[i] = i & 0xff;
1117 ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1118 error = GetLastError();
1119 reply = (ICMP_ECHO_REPLY *)replydata;
1120 ok(ret, "IcmpSendEcho failed unexpectedly\n");
1121 ok(error == NO_ERROR, "Expect last error:0x%08x, got:0x%08x\n", NO_ERROR, error);
1122 ok(INADDR_LOOPBACK == ntohl(reply->Address), "Address mismatch, expect:%s, got: %s\n", ntoa(INADDR_LOOPBACK),
1123 ntoa(reply->Address));
1124 ok(reply->Status == IP_SUCCESS, "Expect status:0x%08x, got:0x%08x\n", IP_SUCCESS, reply->Status);
1125 ok(reply->DataSize == sizeof(senddata), "Got size:%d\n", reply->DataSize);
1126 ok(!memcmp(senddata, reply->Data, min(sizeof(senddata), reply->DataSize)), "Data mismatch\n");
1130 still-to-be-tested NT4-onward functions:
1131 CreateIpForwardEntry
1132 DeleteIpForwardEntry
1133 CreateIpNetEntry
1134 DeleteIpNetEntry
1135 GetFriendlyIfIndex
1136 GetRTTAndHopCount
1137 SetIfEntry
1138 SetIpForwardEntry
1139 SetIpNetEntry
1140 SetIpStatistics
1141 SetIpTTL
1143 static void testWinNT4Functions(void)
1145 testGetNumberOfInterfaces();
1146 testGetIpAddrTable();
1147 testGetIfTable();
1148 testGetIpForwardTable();
1149 testGetIpNetTable();
1150 testGetIcmpStatistics();
1151 testGetIpStatistics();
1152 testGetTcpStatistics();
1153 testGetUdpStatistics();
1154 testGetIcmpStatisticsEx();
1155 testGetIpStatisticsEx();
1156 testGetTcpStatisticsEx();
1157 testGetUdpStatisticsEx();
1158 testGetTcpTable();
1159 testGetUdpTable();
1160 testSetTcpEntry();
1161 testIcmpSendEcho();
1164 static void testGetInterfaceInfo(void)
1166 if (pGetInterfaceInfo) {
1167 DWORD apiReturn;
1168 ULONG len = 0;
1170 apiReturn = pGetInterfaceInfo(NULL, NULL);
1171 if (apiReturn == ERROR_NOT_SUPPORTED) {
1172 skip("GetInterfaceInfo is not supported\n");
1173 return;
1175 ok(apiReturn == ERROR_INVALID_PARAMETER,
1176 "GetInterfaceInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
1177 apiReturn);
1178 apiReturn = pGetInterfaceInfo(NULL, &len);
1179 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
1180 "GetInterfaceInfo returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
1181 apiReturn);
1182 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
1183 PIP_INTERFACE_INFO buf = HeapAlloc(GetProcessHeap(), 0, len);
1185 apiReturn = pGetInterfaceInfo(buf, &len);
1186 ok(apiReturn == NO_ERROR,
1187 "GetInterfaceInfo(buf, &dwSize) returned %d, expected NO_ERROR\n",
1188 apiReturn);
1189 HeapFree(GetProcessHeap(), 0, buf);
1194 static void testGetAdaptersInfo(void)
1196 if (pGetAdaptersInfo) {
1197 DWORD apiReturn;
1198 ULONG len = 0;
1200 apiReturn = pGetAdaptersInfo(NULL, NULL);
1201 if (apiReturn == ERROR_NOT_SUPPORTED) {
1202 skip("GetAdaptersInfo is not supported\n");
1203 return;
1205 ok(apiReturn == ERROR_INVALID_PARAMETER,
1206 "GetAdaptersInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
1207 apiReturn);
1208 apiReturn = pGetAdaptersInfo(NULL, &len);
1209 ok(apiReturn == ERROR_NO_DATA || apiReturn == ERROR_BUFFER_OVERFLOW,
1210 "GetAdaptersInfo returned %d, expected ERROR_NO_DATA or ERROR_BUFFER_OVERFLOW\n",
1211 apiReturn);
1212 if (apiReturn == ERROR_NO_DATA)
1213 ; /* no adapter's, that's okay */
1214 else if (apiReturn == ERROR_BUFFER_OVERFLOW) {
1215 PIP_ADAPTER_INFO ptr, buf = HeapAlloc(GetProcessHeap(), 0, len);
1217 apiReturn = pGetAdaptersInfo(buf, &len);
1218 ok(apiReturn == NO_ERROR,
1219 "GetAdaptersInfo(buf, &dwSize) returned %d, expected NO_ERROR\n",
1220 apiReturn);
1221 ptr = buf;
1222 while (ptr) {
1223 ok(ptr->IpAddressList.IpAddress.String[0], "A valid IP must be present\n");
1224 ok(ptr->IpAddressList.IpMask.String[0], "A valid mask must be present\n");
1225 trace("Adapter '%s', IP %s, Mask %s\n", ptr->AdapterName,
1226 ptr->IpAddressList.IpAddress.String, ptr->IpAddressList.IpMask.String);
1227 ptr = ptr->Next;
1229 HeapFree(GetProcessHeap(), 0, buf);
1234 static void testGetNetworkParams(void)
1236 if (pGetNetworkParams) {
1237 DWORD apiReturn;
1238 ULONG len = 0;
1240 apiReturn = pGetNetworkParams(NULL, NULL);
1241 if (apiReturn == ERROR_NOT_SUPPORTED) {
1242 skip("GetNetworkParams is not supported\n");
1243 return;
1245 ok(apiReturn == ERROR_INVALID_PARAMETER,
1246 "GetNetworkParams returned %d, expected ERROR_INVALID_PARAMETER\n",
1247 apiReturn);
1248 apiReturn = pGetNetworkParams(NULL, &len);
1249 ok(apiReturn == ERROR_BUFFER_OVERFLOW,
1250 "GetNetworkParams returned %d, expected ERROR_BUFFER_OVERFLOW\n",
1251 apiReturn);
1252 if (apiReturn == ERROR_BUFFER_OVERFLOW) {
1253 PFIXED_INFO buf = HeapAlloc(GetProcessHeap(), 0, len);
1255 apiReturn = pGetNetworkParams(buf, &len);
1256 ok(apiReturn == NO_ERROR,
1257 "GetNetworkParams(buf, &dwSize) returned %d, expected NO_ERROR\n",
1258 apiReturn);
1259 HeapFree(GetProcessHeap(), 0, buf);
1265 still-to-be-tested 98-onward functions:
1266 GetBestInterface
1267 GetBestRoute
1268 IpReleaseAddress
1269 IpRenewAddress
1271 static DWORD CALLBACK testWin98Functions(void *p)
1273 testGetInterfaceInfo();
1274 testGetAdaptersInfo();
1275 testGetNetworkParams();
1276 return 0;
1279 static void testGetPerAdapterInfo(void)
1281 DWORD ret, needed;
1282 void *buffer;
1284 if (!pGetPerAdapterInfo) return;
1285 ret = pGetPerAdapterInfo(1, NULL, NULL);
1286 if (ret == ERROR_NOT_SUPPORTED) {
1287 skip("GetPerAdapterInfo is not supported\n");
1288 return;
1290 ok( ret == ERROR_INVALID_PARAMETER, "got %u instead of ERROR_INVALID_PARAMETER\n", ret );
1291 needed = 0xdeadbeef;
1292 ret = pGetPerAdapterInfo(1, NULL, &needed);
1293 if (ret == ERROR_NO_DATA) return; /* no such adapter */
1294 ok( ret == ERROR_BUFFER_OVERFLOW, "got %u instead of ERROR_BUFFER_OVERFLOW\n", ret );
1295 ok( needed != 0xdeadbeef, "needed not set\n" );
1296 buffer = HeapAlloc( GetProcessHeap(), 0, needed );
1297 ret = pGetPerAdapterInfo(1, buffer, &needed);
1298 ok( ret == NO_ERROR, "got %u instead of NO_ERROR\n", ret );
1299 HeapFree( GetProcessHeap(), 0, buffer );
1302 static void testNotifyAddrChange(void)
1304 DWORD ret, bytes;
1305 OVERLAPPED overlapped;
1306 HANDLE handle;
1307 BOOL success;
1309 if (!pNotifyAddrChange)
1311 win_skip("NotifyAddrChange not present\n");
1312 return;
1314 if (!pCancelIPChangeNotify)
1316 win_skip("CancelIPChangeNotify not present\n");
1317 return;
1320 handle = NULL;
1321 ZeroMemory(&overlapped, sizeof(overlapped));
1322 ret = pNotifyAddrChange(&handle, &overlapped);
1323 if (ret == ERROR_NOT_SUPPORTED)
1325 win_skip("NotifyAddrChange is not supported\n");
1326 return;
1328 ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %d, expected ERROR_IO_PENDING\n", ret);
1329 ret = GetLastError();
1330 todo_wine ok(ret == ERROR_IO_PENDING, "GetLastError returned %d, expected ERROR_IO_PENDING\n", ret);
1331 success = pCancelIPChangeNotify(&overlapped);
1332 todo_wine ok(success == TRUE, "CancelIPChangeNotify returned FALSE, expected TRUE\n");
1334 ZeroMemory(&overlapped, sizeof(overlapped));
1335 success = pCancelIPChangeNotify(&overlapped);
1336 ok(success == FALSE, "CancelIPChangeNotify returned TRUE, expected FALSE\n");
1338 handle = NULL;
1339 ZeroMemory(&overlapped, sizeof(overlapped));
1340 overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1341 ret = pNotifyAddrChange(&handle, &overlapped);
1342 ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %d, expected ERROR_IO_PENDING\n", ret);
1343 todo_wine ok(handle != INVALID_HANDLE_VALUE, "NotifyAddrChange returned invalid file handle\n");
1344 success = GetOverlappedResult(handle, &overlapped, &bytes, FALSE);
1345 ok(success == FALSE, "GetOverlappedResult returned TRUE, expected FALSE\n");
1346 ret = GetLastError();
1347 ok(ret == ERROR_IO_INCOMPLETE, "GetLastError returned %d, expected ERROR_IO_INCOMPLETE\n", ret);
1348 success = pCancelIPChangeNotify(&overlapped);
1349 todo_wine ok(success == TRUE, "CancelIPChangeNotify returned FALSE, expected TRUE\n");
1351 if (winetest_interactive)
1353 handle = NULL;
1354 ZeroMemory(&overlapped, sizeof(overlapped));
1355 overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1356 trace("Testing asynchronous ipv4 address change notification. Please "
1357 "change the ipv4 address of one of your network interfaces\n");
1358 ret = pNotifyAddrChange(&handle, &overlapped);
1359 ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %d, expected NO_ERROR\n", ret);
1360 success = GetOverlappedResult(handle, &overlapped, &bytes, TRUE);
1361 ok(success == TRUE, "GetOverlappedResult returned FALSE, expected TRUE\n");
1364 /* test synchronous functionality */
1365 if (winetest_interactive)
1367 trace("Testing synchronous ipv4 address change notification. Please "
1368 "change the ipv4 address of one of your network interfaces\n");
1369 ret = pNotifyAddrChange(NULL, NULL);
1370 todo_wine ok(ret == NO_ERROR, "NotifyAddrChange returned %d, expected NO_ERROR\n", ret);
1375 still-to-be-tested 2K-onward functions:
1376 AddIPAddress
1377 CreateProxyArpEntry
1378 DeleteIPAddress
1379 DeleteProxyArpEntry
1380 EnableRouter
1381 FlushIpNetTable
1382 GetAdapterIndex
1383 NotifyRouteChange + CancelIPChangeNotify
1384 SendARP
1385 UnenableRouter
1387 static void testWin2KFunctions(void)
1389 testGetPerAdapterInfo();
1390 testNotifyAddrChange();
1393 static void test_GetAdaptersAddresses(void)
1395 ULONG ret, size, osize, i;
1396 IP_ADAPTER_ADDRESSES *aa, *ptr;
1397 IP_ADAPTER_UNICAST_ADDRESS *ua;
1399 if (!pGetAdaptersAddresses)
1401 win_skip("GetAdaptersAddresses not present\n");
1402 return;
1405 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, NULL);
1406 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", ret);
1408 /* size should be ignored and overwritten if buffer is NULL */
1409 size = 0x7fffffff;
1410 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
1411 ok(ret == ERROR_BUFFER_OVERFLOW, "expected ERROR_BUFFER_OVERFLOW, got %u\n", ret);
1412 if (ret != ERROR_BUFFER_OVERFLOW) return;
1414 ptr = HeapAlloc(GetProcessHeap(), 0, size);
1415 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, ptr, &size);
1416 ok(!ret, "expected ERROR_SUCCESS got %u\n", ret);
1417 HeapFree(GetProcessHeap(), 0, ptr);
1419 /* higher size must not be changed to lower size */
1420 size *= 2;
1421 osize = size;
1422 ptr = HeapAlloc(GetProcessHeap(), 0, osize);
1423 ret = pGetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, ptr, &osize);
1424 ok(!ret, "expected ERROR_SUCCESS got %u\n", ret);
1425 ok(osize == size, "expected %d, got %d\n", size, osize);
1427 for (aa = ptr; !ret && aa; aa = aa->Next)
1429 char temp[128], buf[39];
1430 IP_ADAPTER_PREFIX *prefix;
1431 DWORD status;
1432 GUID guid;
1434 ok(S(U(*aa)).Length == sizeof(IP_ADAPTER_ADDRESSES_LH) ||
1435 S(U(*aa)).Length == sizeof(IP_ADAPTER_ADDRESSES_XP),
1436 "Unknown structure size of %u bytes\n", S(U(*aa)).Length);
1437 ok(aa->DnsSuffix != NULL, "DnsSuffix is not a valid pointer\n");
1438 ok(aa->Description != NULL, "Description is not a valid pointer\n");
1439 ok(aa->FriendlyName != NULL, "FriendlyName is not a valid pointer\n");
1441 for (i = 0; i < aa->PhysicalAddressLength; i++)
1442 sprintf(temp + i * 3, "%02X-", aa->PhysicalAddress[i]);
1443 temp[i ? i * 3 - 1 : 0] = '\0';
1444 trace("idx %u name %s %s dns %s descr %s phys %s mtu %u flags %08x type %u\n",
1445 S(U(*aa)).IfIndex, aa->AdapterName,
1446 wine_dbgstr_w(aa->FriendlyName), wine_dbgstr_w(aa->DnsSuffix),
1447 wine_dbgstr_w(aa->Description), temp, aa->Mtu, aa->Flags, aa->IfType );
1448 ua = aa->FirstUnicastAddress;
1449 while (ua)
1451 ok(S(U(*ua)).Length == sizeof(IP_ADAPTER_UNICAST_ADDRESS_LH) ||
1452 S(U(*ua)).Length == sizeof(IP_ADAPTER_UNICAST_ADDRESS_XP),
1453 "Unknown structure size of %u bytes\n", S(U(*ua)).Length);
1454 ok(ua->PrefixOrigin != IpPrefixOriginOther,
1455 "bad address config value %d\n", ua->PrefixOrigin);
1456 ok(ua->SuffixOrigin != IpSuffixOriginOther,
1457 "bad address config value %d\n", ua->PrefixOrigin);
1458 /* Address configured manually or from DHCP server? */
1459 if (ua->PrefixOrigin == IpPrefixOriginManual ||
1460 ua->PrefixOrigin == IpPrefixOriginDhcp)
1462 ok(ua->ValidLifetime, "expected non-zero value\n");
1463 ok(ua->PreferredLifetime, "expected non-zero value\n");
1464 ok(ua->LeaseLifetime, "expected non-zero\n");
1466 /* Is the address ok in the network (not duplicated)? */
1467 ok(ua->DadState != IpDadStateInvalid && ua->DadState != IpDadStateDuplicate,
1468 "bad address duplication value %d\n", ua->DadState);
1469 trace(" flags %08x origin %u/%u state %u lifetime %u/%u/%u prefix %u\n",
1470 S(U(*ua)).Flags, ua->PrefixOrigin, ua->SuffixOrigin, ua->DadState,
1471 ua->ValidLifetime, ua->PreferredLifetime, ua->LeaseLifetime,
1472 S(U(*ua)).Length < sizeof(IP_ADAPTER_UNICAST_ADDRESS_LH) ? 0 : ua->OnLinkPrefixLength);
1473 ua = ua->Next;
1475 for (i = 0, temp[0] = '\0'; i < ARRAY_SIZE(aa->ZoneIndices); i++)
1476 sprintf(temp + strlen(temp), "%d ", aa->ZoneIndices[i]);
1477 trace("status %u index %u zone %s\n", aa->OperStatus, aa->Ipv6IfIndex, temp );
1478 prefix = aa->FirstPrefix;
1479 while (prefix)
1481 trace( " prefix %u/%u flags %08x\n", prefix->Address.iSockaddrLength,
1482 prefix->PrefixLength, S(U(*prefix)).Flags );
1483 prefix = prefix->Next;
1486 if (S(U(*aa)).Length < sizeof(IP_ADAPTER_ADDRESSES_LH)) continue;
1487 trace("speed %s/%s metrics %u/%u guid %s type %u/%u\n",
1488 wine_dbgstr_longlong(aa->TransmitLinkSpeed),
1489 wine_dbgstr_longlong(aa->ReceiveLinkSpeed),
1490 aa->Ipv4Metric, aa->Ipv6Metric, wine_dbgstr_guid((GUID*) &aa->NetworkGuid),
1491 aa->ConnectionType, aa->TunnelType);
1493 if (pConvertInterfaceLuidToGuid)
1495 status = pConvertInterfaceLuidToGuid(&aa->Luid, &guid);
1496 ok(!status, "got %u\n", status);
1497 sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1498 guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1],
1499 guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5],
1500 guid.Data4[6], guid.Data4[7]);
1501 ok(!strcasecmp(aa->AdapterName, buf), "expected '%s' got '%s'\n", aa->AdapterName, buf);
1504 HeapFree(GetProcessHeap(), 0, ptr);
1507 static void test_GetExtendedTcpTable(void)
1509 DWORD ret, size;
1510 MIB_TCPTABLE *table;
1511 MIB_TCPTABLE_OWNER_PID *table_pid;
1512 MIB_TCPTABLE_OWNER_MODULE *table_module;
1514 if (!pGetExtendedTcpTable)
1516 win_skip("GetExtendedTcpTable not available\n");
1517 return;
1519 ret = pGetExtendedTcpTable( NULL, NULL, TRUE, AF_INET, TCP_TABLE_BASIC_ALL, 0 );
1520 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1522 size = 0;
1523 ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_BASIC_ALL, 0 );
1524 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1526 table = HeapAlloc( GetProcessHeap(), 0, size );
1527 ret = pGetExtendedTcpTable( table, &size, TRUE, AF_INET, TCP_TABLE_BASIC_ALL, 0 );
1528 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1529 HeapFree( GetProcessHeap(), 0, table );
1531 size = 0;
1532 ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_BASIC_LISTENER, 0 );
1533 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1535 table = HeapAlloc( GetProcessHeap(), 0, size );
1536 ret = pGetExtendedTcpTable( table, &size, TRUE, AF_INET, TCP_TABLE_BASIC_LISTENER, 0 );
1537 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1538 HeapFree( GetProcessHeap(), 0, table );
1540 size = 0;
1541 ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0 );
1542 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1544 table_pid = HeapAlloc( GetProcessHeap(), 0, size );
1545 ret = pGetExtendedTcpTable( table_pid, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0 );
1546 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1547 HeapFree( GetProcessHeap(), 0, table_pid );
1549 size = 0;
1550 ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0 );
1551 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1553 table_pid = HeapAlloc( GetProcessHeap(), 0, size );
1554 ret = pGetExtendedTcpTable( table_pid, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0 );
1555 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1556 HeapFree( GetProcessHeap(), 0, table_pid );
1558 size = 0;
1559 ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0 );
1560 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1562 table_module = HeapAlloc( GetProcessHeap(), 0, size );
1563 ret = pGetExtendedTcpTable( table_module, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0 );
1564 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1565 HeapFree( GetProcessHeap(), 0, table_module );
1567 size = 0;
1568 ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_LISTENER, 0 );
1569 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1571 table_module = HeapAlloc( GetProcessHeap(), 0, size );
1572 ret = pGetExtendedTcpTable( table_module, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_LISTENER, 0 );
1573 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1574 HeapFree( GetProcessHeap(), 0, table_module );
1577 static void test_AllocateAndGetTcpExTableFromStack(void)
1579 DWORD ret;
1580 MIB_TCPTABLE_OWNER_PID *table_ex = NULL;
1582 if (!pAllocateAndGetTcpExTableFromStack)
1584 skip("AllocateAndGetTcpExTableFromStack not available\n");
1585 return;
1588 if (0)
1590 /* crashes on native */
1591 ret = pAllocateAndGetTcpExTableFromStack( NULL, FALSE, INVALID_HANDLE_VALUE, 0, 0 );
1592 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1593 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, INVALID_HANDLE_VALUE, 0, AF_INET );
1594 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1595 ret = pAllocateAndGetTcpExTableFromStack( NULL, FALSE, GetProcessHeap(), 0, AF_INET );
1596 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1599 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, GetProcessHeap(), 0, 0 );
1600 ok( ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_NOT_SUPPORTED) /* win2k */, "got %u\n", ret );
1602 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, GetProcessHeap(), 0, AF_INET );
1603 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1605 if (ret == NO_ERROR && winetest_debug > 1)
1607 DWORD i;
1608 trace( "AllocateAndGetTcpExTableFromStack table: %u entries\n", table_ex->dwNumEntries );
1609 for (i = 0; i < table_ex->dwNumEntries; i++)
1611 char remote_ip[16];
1613 strcpy(remote_ip, ntoa(table_ex->table[i].dwRemoteAddr));
1614 trace( "%u: local %s:%u remote %s:%u state %u pid %u\n", i,
1615 ntoa(table_ex->table[i].dwLocalAddr), ntohs(table_ex->table[i].dwLocalPort),
1616 remote_ip, ntohs(table_ex->table[i].dwRemotePort),
1617 U(table_ex->table[i]).dwState, table_ex->table[i].dwOwningPid );
1620 HeapFree(GetProcessHeap(), 0, table_ex);
1622 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, GetProcessHeap(), 0, AF_INET6 );
1623 ok( ret == ERROR_NOT_SUPPORTED, "got %u\n", ret );
1626 static void test_GetExtendedUdpTable(void)
1628 DWORD ret, size;
1629 MIB_UDPTABLE *table;
1630 MIB_UDPTABLE_OWNER_PID *table_pid;
1631 MIB_UDPTABLE_OWNER_MODULE *table_module;
1633 if (!pGetExtendedUdpTable)
1635 win_skip("GetExtendedUdpTable not available\n");
1636 return;
1638 ret = pGetExtendedUdpTable( NULL, NULL, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
1639 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1641 size = 0;
1642 ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
1643 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1645 table = HeapAlloc( GetProcessHeap(), 0, size );
1646 ret = pGetExtendedUdpTable( table, &size, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
1647 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1648 HeapFree( GetProcessHeap(), 0, table );
1650 size = 0;
1651 ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0 );
1652 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1654 table_pid = HeapAlloc( GetProcessHeap(), 0, size );
1655 ret = pGetExtendedUdpTable( table_pid, &size, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0 );
1656 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1657 HeapFree( GetProcessHeap(), 0, table_pid );
1659 size = 0;
1660 ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_OWNER_MODULE, 0 );
1661 ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1663 table_module = HeapAlloc( GetProcessHeap(), 0, size );
1664 ret = pGetExtendedUdpTable( table_module, &size, TRUE, AF_INET, UDP_TABLE_OWNER_MODULE, 0 );
1665 ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1666 HeapFree( GetProcessHeap(), 0, table_module );
1669 static void test_CreateSortedAddressPairs(void)
1671 SOCKADDR_IN6 dst[2];
1672 SOCKADDR_IN6_PAIR *pair;
1673 ULONG pair_count;
1674 DWORD ret;
1676 if (!pCreateSortedAddressPairs)
1678 win_skip( "CreateSortedAddressPairs not available\n" );
1679 return;
1682 memset( dst, 0, sizeof(dst) );
1683 dst[0].sin6_family = AF_INET6;
1684 dst[0].sin6_addr.u.Word[5] = 0xffff;
1685 dst[0].sin6_addr.u.Word[6] = 0x0808;
1686 dst[0].sin6_addr.u.Word[7] = 0x0808;
1688 pair_count = 0xdeadbeef;
1689 ret = pCreateSortedAddressPairs( NULL, 0, dst, 1, 0, NULL, &pair_count );
1690 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1691 ok( pair_count == 0xdeadbeef, "got %u\n", pair_count );
1693 pair = (SOCKADDR_IN6_PAIR *)0xdeadbeef;
1694 pair_count = 0xdeadbeef;
1695 ret = pCreateSortedAddressPairs( NULL, 0, NULL, 1, 0, &pair, &pair_count );
1696 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1697 ok( pair == (SOCKADDR_IN6_PAIR *)0xdeadbeef, "got %p\n", pair );
1698 ok( pair_count == 0xdeadbeef, "got %u\n", pair_count );
1700 pair = NULL;
1701 pair_count = 0xdeadbeef;
1702 ret = pCreateSortedAddressPairs( NULL, 0, dst, 1, 0, &pair, &pair_count );
1703 ok( ret == NO_ERROR, "got %u\n", ret );
1704 ok( pair != NULL, "pair not set\n" );
1705 ok( pair_count >= 1, "got %u\n", pair_count );
1706 ok( pair[0].SourceAddress != NULL, "src address not set\n" );
1707 ok( pair[0].DestinationAddress != NULL, "dst address not set\n" );
1708 pFreeMibTable( pair );
1710 dst[1].sin6_family = AF_INET6;
1711 dst[1].sin6_addr.u.Word[5] = 0xffff;
1712 dst[1].sin6_addr.u.Word[6] = 0x0404;
1713 dst[1].sin6_addr.u.Word[7] = 0x0808;
1715 pair = NULL;
1716 pair_count = 0xdeadbeef;
1717 ret = pCreateSortedAddressPairs( NULL, 0, dst, 2, 0, &pair, &pair_count );
1718 ok( ret == NO_ERROR, "got %u\n", ret );
1719 ok( pair != NULL, "pair not set\n" );
1720 ok( pair_count >= 2, "got %u\n", pair_count );
1721 ok( pair[0].SourceAddress != NULL, "src address not set\n" );
1722 ok( pair[0].DestinationAddress != NULL, "dst address not set\n" );
1723 ok( pair[1].SourceAddress != NULL, "src address not set\n" );
1724 ok( pair[1].DestinationAddress != NULL, "dst address not set\n" );
1725 pFreeMibTable( pair );
1728 static DWORD get_interface_index(void)
1730 DWORD size = 0, ret = 0;
1731 IP_ADAPTER_ADDRESSES *buf, *aa;
1733 if (pGetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size ) != ERROR_BUFFER_OVERFLOW)
1734 return 0;
1736 buf = HeapAlloc( GetProcessHeap(), 0, size );
1737 pGetAdaptersAddresses( AF_UNSPEC, 0, NULL, buf, &size );
1738 for (aa = buf; aa; aa = aa->Next)
1740 if (aa->IfType == IF_TYPE_ETHERNET_CSMACD)
1742 ret = aa->IfIndex;
1743 break;
1746 HeapFree( GetProcessHeap(), 0, buf );
1747 return ret;
1750 static void test_interface_identifier_conversion(void)
1752 DWORD ret;
1753 NET_LUID luid;
1754 GUID guid;
1755 SIZE_T len;
1756 WCHAR nameW[IF_MAX_STRING_SIZE + 1];
1757 char nameA[IF_MAX_STRING_SIZE + 1], *name;
1758 NET_IFINDEX index, index2;
1760 if (!pConvertInterfaceIndexToLuid)
1762 win_skip( "ConvertInterfaceIndexToLuid not available\n" );
1763 return;
1765 if (!(index = get_interface_index()))
1767 skip( "no suitable interface found\n" );
1768 return;
1771 /* ConvertInterfaceIndexToLuid */
1772 ret = pConvertInterfaceIndexToLuid( 0, NULL );
1773 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1775 memset( &luid, 0xff, sizeof(luid) );
1776 ret = pConvertInterfaceIndexToLuid( 0, &luid );
1777 ok( ret == ERROR_FILE_NOT_FOUND, "got %u\n", ret );
1778 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1779 ok( !luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex );
1780 ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType );
1782 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1783 ret = pConvertInterfaceIndexToLuid( index, &luid );
1784 ok( !ret, "got %u\n", ret );
1785 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1786 ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1787 ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1789 /* ConvertInterfaceLuidToIndex */
1790 ret = pConvertInterfaceLuidToIndex( NULL, NULL );
1791 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1793 ret = pConvertInterfaceLuidToIndex( NULL, &index );
1794 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1796 ret = pConvertInterfaceLuidToIndex( &luid, NULL );
1797 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1799 ret = pConvertInterfaceLuidToIndex( &luid, &index );
1800 ok( !ret, "got %u\n", ret );
1802 /* ConvertInterfaceLuidToGuid */
1803 ret = pConvertInterfaceLuidToGuid( NULL, NULL );
1804 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1806 memset( &guid, 0xff, sizeof(guid) );
1807 ret = pConvertInterfaceLuidToGuid( NULL, &guid );
1808 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1809 ok( guid.Data1 == 0xffffffff, "got %x\n", guid.Data1 );
1811 ret = pConvertInterfaceLuidToGuid( &luid, NULL );
1812 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1814 memset( &guid, 0, sizeof(guid) );
1815 ret = pConvertInterfaceLuidToGuid( &luid, &guid );
1816 ok( !ret, "got %u\n", ret );
1817 ok( guid.Data1, "got %x\n", guid.Data1 );
1819 /* ConvertInterfaceGuidToLuid */
1820 ret = pConvertInterfaceGuidToLuid( NULL, NULL );
1821 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1823 luid.Info.NetLuidIndex = 1;
1824 ret = pConvertInterfaceGuidToLuid( NULL, &luid );
1825 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1826 ok( luid.Info.NetLuidIndex == 1, "got %u\n", luid.Info.NetLuidIndex );
1828 ret = pConvertInterfaceGuidToLuid( &guid, NULL );
1829 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1831 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1832 ret = pConvertInterfaceGuidToLuid( &guid, &luid );
1833 ok( !ret, "got %u\n", ret );
1834 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1835 ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1836 ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1838 /* ConvertInterfaceLuidToNameW */
1839 ret = pConvertInterfaceLuidToNameW( NULL, NULL, 0 );
1840 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1842 ret = pConvertInterfaceLuidToNameW( &luid, NULL, 0 );
1843 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1845 ret = pConvertInterfaceLuidToNameW( NULL, nameW, 0 );
1846 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1848 ret = pConvertInterfaceLuidToNameW( &luid, nameW, 0 );
1849 ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret );
1851 nameW[0] = 0;
1852 len = ARRAY_SIZE(nameW);
1853 ret = pConvertInterfaceLuidToNameW( &luid, nameW, len );
1854 ok( !ret, "got %u\n", ret );
1855 ok( nameW[0], "name not set\n" );
1857 /* ConvertInterfaceLuidToNameA */
1858 ret = pConvertInterfaceLuidToNameA( NULL, NULL, 0 );
1859 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1861 ret = pConvertInterfaceLuidToNameA( &luid, NULL, 0 );
1862 ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret );
1864 ret = pConvertInterfaceLuidToNameA( NULL, nameA, 0 );
1865 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1867 ret = pConvertInterfaceLuidToNameA( &luid, nameA, 0 );
1868 ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret );
1870 nameA[0] = 0;
1871 len = ARRAY_SIZE(nameA);
1872 ret = pConvertInterfaceLuidToNameA( &luid, nameA, len );
1873 ok( !ret, "got %u\n", ret );
1874 ok( nameA[0], "name not set\n" );
1876 /* ConvertInterfaceNameToLuidW */
1877 ret = pConvertInterfaceNameToLuidW( NULL, NULL );
1878 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1880 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1881 ret = pConvertInterfaceNameToLuidW( NULL, &luid );
1882 ok( ret == ERROR_INVALID_NAME, "got %u\n", ret );
1883 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1884 ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1885 ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType );
1887 ret = pConvertInterfaceNameToLuidW( nameW, NULL );
1888 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1890 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1891 ret = pConvertInterfaceNameToLuidW( nameW, &luid );
1892 ok( !ret, "got %u\n", ret );
1893 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1894 ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1895 ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1897 /* ConvertInterfaceNameToLuidA */
1898 ret = pConvertInterfaceNameToLuidA( NULL, NULL );
1899 ok( ret == ERROR_INVALID_NAME, "got %u\n", ret );
1901 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1902 ret = pConvertInterfaceNameToLuidA( NULL, &luid );
1903 ok( ret == ERROR_INVALID_NAME, "got %u\n", ret );
1904 ok( luid.Info.Reserved == 0xdead, "reserved set\n" );
1905 ok( luid.Info.NetLuidIndex == 0xdead, "index set\n" );
1906 ok( luid.Info.IfType == 0xdead, "type set\n" );
1908 ret = pConvertInterfaceNameToLuidA( nameA, NULL );
1909 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1911 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1912 ret = pConvertInterfaceNameToLuidA( nameA, &luid );
1913 ok( !ret, "got %u\n", ret );
1914 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1915 ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1916 ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1918 if (!pif_nametoindex || !pif_indextoname)
1920 skip("if_nametoindex/if_indextoname not supported\n");
1921 return;
1924 index2 = pif_nametoindex( NULL );
1925 ok( !index2, "Got unexpected index %u\n", index2 );
1926 index2 = pif_nametoindex( nameA );
1927 ok( index2 == index, "Got index %u for %s, expected %u\n", index2, nameA, index );
1928 /* Wargaming.net Game Center passes a GUID-like string. */
1929 index2 = pif_nametoindex( "{00000001-0000-0000-0000-000000000000}" );
1930 ok( !index2, "Got unexpected index %u\n", index2 );
1931 index2 = pif_nametoindex( wine_dbgstr_guid( &guid ) );
1932 ok( !index2, "Got unexpected index %u for input %s\n", index2, wine_dbgstr_guid( &guid ) );
1934 name = pif_indextoname( 0, NULL );
1935 ok( name == NULL, "got %s\n", name );
1937 name = pif_indextoname( 0, nameA );
1938 ok( name == NULL, "got %p\n", name );
1940 name = pif_indextoname( ~0u, nameA );
1941 ok( name == NULL, "got %p\n", name );
1943 nameA[0] = 0;
1944 name = pif_indextoname( 1, nameA );
1945 if (name != NULL)
1947 ok( name[0], "empty name\n" );
1948 ok( name == nameA, "got %p\n", name );
1952 static void test_GetIfEntry2(void)
1954 DWORD ret;
1955 MIB_IF_ROW2 row;
1956 NET_IFINDEX index;
1958 if (!pGetIfEntry2)
1960 win_skip( "GetIfEntry2 not available\n" );
1961 return;
1963 if (!(index = get_interface_index()))
1965 skip( "no suitable interface found\n" );
1966 return;
1969 ret = pGetIfEntry2( NULL );
1970 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1972 memset( &row, 0, sizeof(row) );
1973 ret = pGetIfEntry2( &row );
1974 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1976 memset( &row, 0, sizeof(row) );
1977 row.InterfaceIndex = index;
1978 ret = pGetIfEntry2( &row );
1979 ok( ret == NO_ERROR, "got %u\n", ret );
1980 ok( row.InterfaceIndex == index, "got %u\n", index );
1983 static void test_GetIfTable2(void)
1985 DWORD ret;
1986 MIB_IF_TABLE2 *table;
1988 if (!pGetIfTable2)
1990 win_skip( "GetIfTable2 not available\n" );
1991 return;
1994 table = NULL;
1995 ret = pGetIfTable2( &table );
1996 ok( ret == NO_ERROR, "got %u\n", ret );
1997 ok( table != NULL, "table not set\n" );
1998 pFreeMibTable( table );
2001 static void test_GetIfTable2Ex(void)
2003 DWORD ret;
2004 MIB_IF_TABLE2 *table;
2006 if (!pGetIfTable2Ex)
2008 win_skip( "GetIfTable2Ex not available\n" );
2009 return;
2012 table = NULL;
2013 ret = pGetIfTable2Ex( MibIfTableNormal, &table );
2014 ok( ret == NO_ERROR, "got %u\n", ret );
2015 ok( table != NULL, "table not set\n" );
2016 pFreeMibTable( table );
2018 table = NULL;
2019 ret = pGetIfTable2Ex( MibIfTableRaw, &table );
2020 ok( ret == NO_ERROR, "got %u\n", ret );
2021 ok( table != NULL, "table not set\n" );
2022 pFreeMibTable( table );
2024 table = NULL;
2025 ret = pGetIfTable2Ex( MibIfTableNormalWithoutStatistics, &table );
2026 ok( ret == NO_ERROR || broken(ret == ERROR_INVALID_PARAMETER), "got %u\n", ret );
2027 ok( table != NULL || broken(!table), "table not set\n" );
2028 pFreeMibTable( table );
2030 table = NULL;
2031 ret = pGetIfTable2Ex( 3, &table );
2032 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
2033 ok( !table, "table should not be set\n" );
2034 pFreeMibTable( table );
2037 static void test_GetUnicastIpAddressEntry(void)
2039 IP_ADAPTER_ADDRESSES *aa, *ptr;
2040 MIB_UNICASTIPADDRESS_ROW row;
2041 DWORD ret, size;
2043 if (!pGetUnicastIpAddressEntry)
2045 win_skip( "GetUnicastIpAddressEntry not available\n" );
2046 return;
2049 ret = pGetUnicastIpAddressEntry( NULL );
2050 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
2052 memset( &row, 0, sizeof(row) );
2053 ret = pGetUnicastIpAddressEntry( &row );
2054 todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
2056 memset( &row, 0, sizeof(row) );
2057 row.Address.Ipv4.sin_family = AF_INET;
2058 row.Address.Ipv4.sin_port = 0;
2059 row.Address.Ipv4.sin_addr.S_un.S_addr = 0x01020304;
2060 ret = pGetUnicastIpAddressEntry( &row );
2061 ok( ret == ERROR_FILE_NOT_FOUND, "got %u\n", ret );
2063 memset( &row, 0, sizeof(row) );
2064 row.InterfaceIndex = 123;
2065 ret = pGetUnicastIpAddressEntry( &row );
2066 todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
2068 memset( &row, 0, sizeof(row) );
2069 row.InterfaceIndex = get_interface_index();
2070 row.Address.Ipv4.sin_family = AF_INET;
2071 row.Address.Ipv4.sin_port = 0;
2072 row.Address.Ipv4.sin_addr.S_un.S_addr = 0x01020304;
2073 ret = pGetUnicastIpAddressEntry( &row );
2074 ok( ret == ERROR_NOT_FOUND, "got %u\n", ret );
2076 memset( &row, 0, sizeof(row) );
2077 row.InterfaceIndex = 123;
2078 row.Address.Ipv4.sin_family = AF_INET;
2079 row.Address.Ipv4.sin_port = 0;
2080 row.Address.Ipv4.sin_addr.S_un.S_addr = 0x01020304;
2081 ret = pGetUnicastIpAddressEntry( &row );
2082 ok( ret == ERROR_FILE_NOT_FOUND, "got %u\n", ret );
2084 ret = pGetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_INTERFACES, NULL, NULL, &size);
2085 ok(ret == ERROR_BUFFER_OVERFLOW, "expected ERROR_BUFFER_OVERFLOW, got %u\n", ret);
2086 if (ret != ERROR_BUFFER_OVERFLOW) return;
2088 ptr = HeapAlloc(GetProcessHeap(), 0, size);
2089 ret = pGetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_INTERFACES, NULL, ptr, &size);
2090 ok(!ret, "expected ERROR_SUCCESS got %u\n", ret);
2092 for (aa = ptr; !ret && aa; aa = aa->Next)
2094 IP_ADAPTER_UNICAST_ADDRESS *ua;
2096 ua = aa->FirstUnicastAddress;
2097 while (ua)
2099 /* test with luid */
2100 memset( &row, 0, sizeof(row) );
2101 memcpy(&row.InterfaceLuid, &aa->Luid, sizeof(aa->Luid));
2102 memcpy(&row.Address, ua->Address.lpSockaddr, ua->Address.iSockaddrLength);
2103 ret = pGetUnicastIpAddressEntry( &row );
2104 ok( ret == NO_ERROR, "got %u\n", ret );
2106 /* test with index */
2107 memset( &row, 0, sizeof(row) );
2108 row.InterfaceIndex = S(U(*aa)).IfIndex;
2109 memcpy(&row.Address, ua->Address.lpSockaddr, ua->Address.iSockaddrLength);
2110 ret = pGetUnicastIpAddressEntry( &row );
2111 ok( ret == NO_ERROR, "got %u\n", ret );
2112 if (ret == NO_ERROR)
2114 ok(row.InterfaceLuid.Info.Reserved == aa->Luid.Info.Reserved, "Expected %d, got %d\n",
2115 aa->Luid.Info.Reserved, row.InterfaceLuid.Info.Reserved);
2116 ok(row.InterfaceLuid.Info.NetLuidIndex == aa->Luid.Info.NetLuidIndex, "Expected %d, got %d\n",
2117 aa->Luid.Info.NetLuidIndex, row.InterfaceLuid.Info.NetLuidIndex);
2118 ok(row.InterfaceLuid.Info.IfType == aa->Luid.Info.IfType, "Expected %d, got %d\n",
2119 aa->Luid.Info.IfType, row.InterfaceLuid.Info.IfType);
2120 ok(row.InterfaceIndex == S(U(*aa)).IfIndex, "Expected %d, got %d\n",
2121 S(U(*aa)).IfIndex, row.InterfaceIndex);
2122 ok(row.PrefixOrigin == ua->PrefixOrigin, "Expected %d, got %d\n",
2123 ua->PrefixOrigin, row.PrefixOrigin);
2124 ok(row.SuffixOrigin == ua->SuffixOrigin, "Expected %d, got %d\n",
2125 ua->SuffixOrigin, row.SuffixOrigin);
2126 ok(row.ValidLifetime == ua->ValidLifetime, "Expected %d, got %d\n",
2127 ua->ValidLifetime, row.ValidLifetime);
2128 ok(row.PreferredLifetime == ua->PreferredLifetime, "Expected %d, got %d\n",
2129 ua->PreferredLifetime, row.PreferredLifetime);
2130 ok(row.OnLinkPrefixLength == ua->OnLinkPrefixLength, "Expected %d, got %d\n",
2131 ua->OnLinkPrefixLength, row.OnLinkPrefixLength);
2132 ok(row.SkipAsSource == 0, "Expected 0, got %d\n", row.SkipAsSource);
2133 ok(row.DadState == ua->DadState, "Expected %d, got %d\n", ua->DadState, row.DadState);
2134 if (row.Address.si_family == AF_INET6)
2135 ok(row.ScopeId.Value == row.Address.Ipv6.sin6_scope_id, "Expected %d, got %d\n",
2136 row.Address.Ipv6.sin6_scope_id, row.ScopeId.Value);
2137 ok(row.CreationTimeStamp.QuadPart, "CreationTimeStamp is 0\n");
2139 ua = ua->Next;
2142 HeapFree(GetProcessHeap(), 0, ptr);
2145 static void test_GetUnicastIpAddressTable(void)
2147 MIB_UNICASTIPADDRESS_TABLE *table;
2148 DWORD ret;
2149 ULONG i;
2151 if (!pGetUnicastIpAddressTable)
2153 win_skip( "GetUnicastIpAddressTable not available\n" );
2154 return;
2157 ret = pGetUnicastIpAddressTable(AF_UNSPEC, NULL);
2158 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
2160 ret = pGetUnicastIpAddressTable(AF_BAN, &table);
2161 ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
2163 ret = pGetUnicastIpAddressTable(AF_INET, &table);
2164 ok( ret == NO_ERROR, "got %u\n", ret );
2165 trace("GetUnicastIpAddressTable(AF_INET): NumEntries %u\n", table->NumEntries);
2166 pFreeMibTable(table);
2168 ret = pGetUnicastIpAddressTable(AF_INET6, &table);
2169 ok( ret == NO_ERROR, "got %u\n", ret );
2170 trace("GetUnicastIpAddressTable(AF_INET6): NumEntries %u\n", table->NumEntries);
2171 pFreeMibTable(table);
2173 ret = pGetUnicastIpAddressTable(AF_UNSPEC, &table);
2174 ok( ret == NO_ERROR, "got %u\n", ret );
2175 trace("GetUnicastIpAddressTable(AF_UNSPEC): NumEntries %u\n", table->NumEntries);
2176 for (i = 0; i < table->NumEntries && winetest_debug > 1; i++)
2178 trace("Index %u:\n", i);
2179 trace("Address.si_family: %u\n", table->Table[i].Address.si_family);
2180 trace("InterfaceLuid.Info.Reserved: %u\n", table->Table[i].InterfaceLuid.Info.Reserved);
2181 trace("InterfaceLuid.Info.NetLuidIndex: %u\n", table->Table[i].InterfaceLuid.Info.NetLuidIndex);
2182 trace("InterfaceLuid.Info.IfType: %u\n", table->Table[i].InterfaceLuid.Info.IfType);
2183 trace("InterfaceIndex: %u\n", table->Table[i].InterfaceIndex);
2184 trace("PrefixOrigin: %u\n", table->Table[i].PrefixOrigin);
2185 trace("SuffixOrigin: %u\n", table->Table[i].SuffixOrigin);
2186 trace("ValidLifetime: %u seconds\n", table->Table[i].ValidLifetime);
2187 trace("PreferredLifetime: %u seconds\n", table->Table[i].PreferredLifetime);
2188 trace("OnLinkPrefixLength: %u\n", table->Table[i].OnLinkPrefixLength);
2189 trace("SkipAsSource: %u\n", table->Table[i].SkipAsSource);
2190 trace("DadState: %u\n", table->Table[i].DadState);
2191 trace("ScopeId.Value: %u\n", table->Table[i].ScopeId.Value);
2192 trace("CreationTimeStamp: %08x%08x\n", table->Table[i].CreationTimeStamp.HighPart, table->Table[i].CreationTimeStamp.LowPart);
2195 pFreeMibTable(table);
2198 static void test_ConvertLengthToIpv4Mask(void)
2200 DWORD ret;
2201 DWORD n;
2202 ULONG mask;
2203 ULONG expected;
2205 if (!pConvertLengthToIpv4Mask)
2207 win_skip( "ConvertLengthToIpv4Mask not available\n" );
2208 return;
2211 for (n = 0; n <= 32; n++)
2213 mask = 0xdeadbeef;
2214 if (n > 0)
2215 expected = htonl( ~0u << (32 - n) );
2216 else
2217 expected = 0;
2219 ret = pConvertLengthToIpv4Mask( n, &mask );
2220 ok( ret == NO_ERROR, "ConvertLengthToIpv4Mask returned 0x%08x, expected 0x%08x\n", ret, NO_ERROR );
2221 ok( mask == expected, "ConvertLengthToIpv4Mask mask value 0x%08x, expected 0x%08x\n", mask, expected );
2224 /* Testing for out of range. In this case both mask and return are changed to indicate error. */
2225 mask = 0xdeadbeef;
2226 ret = pConvertLengthToIpv4Mask( 33, &mask );
2227 ok( ret == ERROR_INVALID_PARAMETER, "ConvertLengthToIpv4Mask returned 0x%08x, expected 0x%08x\n", ret, ERROR_INVALID_PARAMETER );
2228 ok( mask == INADDR_NONE, "ConvertLengthToIpv4Mask mask value 0x%08x, expected 0x%08x\n", mask, INADDR_NONE );
2231 START_TEST(iphlpapi)
2234 loadIPHlpApi();
2235 if (hLibrary) {
2236 HANDLE thread;
2238 testWin98OnlyFunctions();
2239 testWinNT4Functions();
2241 /* run testGetXXXX in two threads at once to make sure we don't crash in that case */
2242 thread = CreateThread(NULL, 0, testWin98Functions, NULL, 0, NULL);
2243 testWin98Functions(NULL);
2244 WaitForSingleObject(thread, INFINITE);
2246 testWin2KFunctions();
2247 test_GetAdaptersAddresses();
2248 test_GetExtendedTcpTable();
2249 test_GetExtendedUdpTable();
2250 test_AllocateAndGetTcpExTableFromStack();
2251 test_CreateSortedAddressPairs();
2252 test_interface_identifier_conversion();
2253 test_GetIfEntry2();
2254 test_GetIfTable2();
2255 test_GetIfTable2Ex();
2256 test_GetUnicastIpAddressEntry();
2257 test_GetUnicastIpAddressTable();
2258 test_ConvertLengthToIpv4Mask();
2259 freeIPHlpApi();