push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / iphlpapi / tests / iphlpapi.c
blobf879c93a9439d055a85d3e22ee5c4211e1af2f5c
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 "iphlpapi.h"
42 #include "iprtrmib.h"
43 #include "wine/test.h"
44 #include <stdio.h>
45 #include <stdlib.h>
47 static HMODULE hLibrary = NULL;
49 typedef DWORD (WINAPI *GetNumberOfInterfacesFunc)(PDWORD);
50 typedef DWORD (WINAPI *GetIpAddrTableFunc)(PMIB_IPADDRTABLE,PULONG,BOOL);
51 typedef DWORD (WINAPI *GetIfEntryFunc)(PMIB_IFROW);
52 typedef DWORD (WINAPI *GetFriendlyIfIndexFunc)(DWORD);
53 typedef DWORD (WINAPI *GetIfTableFunc)(PMIB_IFTABLE,PULONG,BOOL);
54 typedef DWORD (WINAPI *GetIpForwardTableFunc)(PMIB_IPFORWARDTABLE,PULONG,BOOL);
55 typedef DWORD (WINAPI *GetIpNetTableFunc)(PMIB_IPNETTABLE,PULONG,BOOL);
56 typedef DWORD (WINAPI *GetInterfaceInfoFunc)(PIP_INTERFACE_INFO,PULONG);
57 typedef DWORD (WINAPI *GetAdaptersInfoFunc)(PIP_ADAPTER_INFO,PULONG);
58 typedef DWORD (WINAPI *GetNetworkParamsFunc)(PFIXED_INFO,PULONG);
59 typedef DWORD (WINAPI *GetIcmpStatisticsFunc)(PMIB_ICMP);
60 typedef DWORD (WINAPI *GetIpStatisticsFunc)(PMIB_IPSTATS);
61 typedef DWORD (WINAPI *GetTcpStatisticsFunc)(PMIB_TCPSTATS);
62 typedef DWORD (WINAPI *GetUdpStatisticsFunc)(PMIB_UDPSTATS);
63 typedef DWORD (WINAPI *GetTcpTableFunc)(PMIB_TCPTABLE,PDWORD,BOOL);
64 typedef DWORD (WINAPI *GetUdpTableFunc)(PMIB_UDPTABLE,PDWORD,BOOL);
65 typedef DWORD (WINAPI *GetPerAdapterInfoFunc)(ULONG,PIP_PER_ADAPTER_INFO,PULONG);
66 typedef DWORD (WINAPI *GetAdaptersAddressesFunc)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG);
68 static GetNumberOfInterfacesFunc gGetNumberOfInterfaces = NULL;
69 static GetIpAddrTableFunc gGetIpAddrTable = NULL;
70 static GetIfEntryFunc gGetIfEntry = NULL;
71 static GetFriendlyIfIndexFunc gGetFriendlyIfIndex = NULL;
72 static GetIfTableFunc gGetIfTable = NULL;
73 static GetIpForwardTableFunc gGetIpForwardTable = NULL;
74 static GetIpNetTableFunc gGetIpNetTable = NULL;
75 static GetInterfaceInfoFunc gGetInterfaceInfo = NULL;
76 static GetAdaptersInfoFunc gGetAdaptersInfo = NULL;
77 static GetNetworkParamsFunc gGetNetworkParams = NULL;
78 static GetIcmpStatisticsFunc gGetIcmpStatistics = NULL;
79 static GetIpStatisticsFunc gGetIpStatistics = NULL;
80 static GetTcpStatisticsFunc gGetTcpStatistics = NULL;
81 static GetUdpStatisticsFunc gGetUdpStatistics = NULL;
82 static GetTcpTableFunc gGetTcpTable = NULL;
83 static GetUdpTableFunc gGetUdpTable = NULL;
84 static GetPerAdapterInfoFunc gGetPerAdapterInfo = NULL;
85 static GetAdaptersAddressesFunc gGetAdaptersAddresses = NULL;
87 static void loadIPHlpApi(void)
89 hLibrary = LoadLibraryA("iphlpapi.dll");
90 if (hLibrary) {
91 gGetNumberOfInterfaces = (GetNumberOfInterfacesFunc)GetProcAddress(
92 hLibrary, "GetNumberOfInterfaces");
93 gGetIpAddrTable = (GetIpAddrTableFunc)GetProcAddress(
94 hLibrary, "GetIpAddrTable");
95 gGetIfEntry = (GetIfEntryFunc)GetProcAddress(
96 hLibrary, "GetIfEntry");
97 gGetFriendlyIfIndex = (GetFriendlyIfIndexFunc)GetProcAddress(
98 hLibrary, "GetFriendlyIfIndex");
99 gGetIfTable = (GetIfTableFunc)GetProcAddress(
100 hLibrary, "GetIfTable");
101 gGetIpForwardTable = (GetIpForwardTableFunc)GetProcAddress(
102 hLibrary, "GetIpForwardTable");
103 gGetIpNetTable = (GetIpNetTableFunc)GetProcAddress(
104 hLibrary, "GetIpNetTable");
105 gGetInterfaceInfo = (GetInterfaceInfoFunc)GetProcAddress(
106 hLibrary, "GetInterfaceInfo");
107 gGetAdaptersInfo = (GetAdaptersInfoFunc)GetProcAddress(
108 hLibrary, "GetAdaptersInfo");
109 gGetNetworkParams = (GetNetworkParamsFunc)GetProcAddress(
110 hLibrary, "GetNetworkParams");
111 gGetIcmpStatistics = (GetIcmpStatisticsFunc)GetProcAddress(
112 hLibrary, "GetIcmpStatistics");
113 gGetIpStatistics = (GetIpStatisticsFunc)GetProcAddress(
114 hLibrary, "GetIpStatistics");
115 gGetTcpStatistics = (GetTcpStatisticsFunc)GetProcAddress(
116 hLibrary, "GetTcpStatistics");
117 gGetUdpStatistics = (GetUdpStatisticsFunc)GetProcAddress(
118 hLibrary, "GetUdpStatistics");
119 gGetTcpTable = (GetTcpTableFunc)GetProcAddress(
120 hLibrary, "GetTcpTable");
121 gGetUdpTable = (GetUdpTableFunc)GetProcAddress(
122 hLibrary, "GetUdpTable");
123 gGetPerAdapterInfo = (GetPerAdapterInfoFunc)GetProcAddress(hLibrary, "GetPerAdapterInfo");
124 gGetAdaptersAddresses = (GetAdaptersAddressesFunc)GetProcAddress(hLibrary, "GetAdaptersAddresses");
128 static void freeIPHlpApi(void)
130 if (hLibrary) {
131 gGetNumberOfInterfaces = NULL;
132 gGetIpAddrTable = NULL;
133 gGetIfEntry = NULL;
134 gGetFriendlyIfIndex = NULL;
135 gGetIfTable = NULL;
136 gGetIpForwardTable = NULL;
137 gGetIpNetTable = NULL;
138 gGetInterfaceInfo = NULL;
139 gGetAdaptersInfo = NULL;
140 gGetNetworkParams = NULL;
141 gGetIcmpStatistics = NULL;
142 gGetIpStatistics = NULL;
143 gGetTcpStatistics = NULL;
144 gGetUdpStatistics = NULL;
145 gGetTcpTable = NULL;
146 gGetUdpTable = NULL;
147 FreeLibrary(hLibrary);
148 hLibrary = NULL;
152 /* replacement for inet_ntoa */
153 static const char *ntoa( DWORD ip )
155 static char buffer[40];
157 ip = htonl(ip);
158 sprintf( buffer, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff );
159 return buffer;
163 still-to-be-tested 98-only functions:
164 GetUniDirectionalAdapterInfo
166 static void testWin98OnlyFunctions(void)
170 static void testGetNumberOfInterfaces(void)
172 if (gGetNumberOfInterfaces) {
173 DWORD apiReturn, numInterfaces;
175 /* Crashes on Vista */
176 if (0) {
177 apiReturn = gGetNumberOfInterfaces(NULL), numInterfaces;
178 if (apiReturn == ERROR_NOT_SUPPORTED)
179 return;
180 ok(apiReturn == ERROR_INVALID_PARAMETER,
181 "GetNumberOfInterfaces(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
182 apiReturn);
185 apiReturn = gGetNumberOfInterfaces(&numInterfaces);
186 if (apiReturn == ERROR_NOT_SUPPORTED) {
187 skip("GetNumberOfInterfaces is not supported\n");
188 return;
190 ok(apiReturn == NO_ERROR,
191 "GetNumberOfInterfaces returned %d, expected 0\n", apiReturn);
195 static void testGetIfEntry(DWORD index)
197 if (gGetIfEntry) {
198 DWORD apiReturn;
199 MIB_IFROW row;
201 memset(&row, 0, sizeof(row));
202 apiReturn = gGetIfEntry(NULL);
203 if (apiReturn == ERROR_NOT_SUPPORTED) {
204 skip("GetIfEntry is not supported\n");
205 return;
207 ok(apiReturn == ERROR_INVALID_PARAMETER,
208 "GetIfEntry(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
209 apiReturn);
210 row.dwIndex = -1; /* hope that's always bogus! */
211 apiReturn = gGetIfEntry(&row);
212 ok(apiReturn == ERROR_INVALID_DATA ||
213 apiReturn == ERROR_FILE_NOT_FOUND /* Vista */,
214 "GetIfEntry(bogus row) returned %d, expected ERROR_INVALID_DATA or ERROR_FILE_NOT_FOUND\n",
215 apiReturn);
216 row.dwIndex = index;
217 apiReturn = gGetIfEntry(&row);
218 ok(apiReturn == NO_ERROR,
219 "GetIfEntry returned %d, expected NO_ERROR\n", apiReturn);
223 static void testGetIpAddrTable(void)
225 if (gGetIpAddrTable) {
226 DWORD apiReturn;
227 ULONG dwSize = 0;
229 apiReturn = gGetIpAddrTable(NULL, NULL, FALSE);
230 if (apiReturn == ERROR_NOT_SUPPORTED) {
231 skip("GetIpAddrTable is not supported\n");
232 return;
234 ok(apiReturn == ERROR_INVALID_PARAMETER,
235 "GetIpAddrTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
236 apiReturn);
237 apiReturn = gGetIpAddrTable(NULL, &dwSize, FALSE);
238 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
239 "GetIpAddrTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
240 apiReturn);
241 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
242 PMIB_IPADDRTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
244 apiReturn = gGetIpAddrTable(buf, &dwSize, FALSE);
245 ok(apiReturn == NO_ERROR,
246 "GetIpAddrTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
247 apiReturn);
248 if (apiReturn == NO_ERROR && buf->dwNumEntries)
249 testGetIfEntry(buf->table[0].dwIndex);
250 HeapFree(GetProcessHeap(), 0, buf);
255 static void testGetIfTable(void)
257 if (gGetIfTable) {
258 DWORD apiReturn;
259 ULONG dwSize = 0;
261 apiReturn = gGetIfTable(NULL, NULL, FALSE);
262 if (apiReturn == ERROR_NOT_SUPPORTED) {
263 skip("GetIfTable is not supported\n");
264 return;
266 ok(apiReturn == ERROR_INVALID_PARAMETER,
267 "GetIfTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
268 apiReturn);
269 apiReturn = gGetIfTable(NULL, &dwSize, FALSE);
270 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
271 "GetIfTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
272 apiReturn);
273 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
274 PMIB_IFTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
276 apiReturn = gGetIfTable(buf, &dwSize, FALSE);
277 ok(apiReturn == NO_ERROR,
278 "GetIfTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n\n",
279 apiReturn);
281 if (apiReturn == NO_ERROR && winetest_debug > 1)
283 DWORD i, j;
284 char name[MAX_INTERFACE_NAME_LEN];
286 trace( "interface table: %u entries\n", buf->dwNumEntries );
287 for (i = 0; i < buf->dwNumEntries; i++)
289 MIB_IFROW *row = &buf->table[i];
290 WideCharToMultiByte( CP_ACP, 0, row->wszName, -1, name, MAX_INTERFACE_NAME_LEN, NULL, NULL );
291 trace( "%u: '%s' type %u mtu %u speed %u phys",
292 row->dwIndex, name, row->dwType, row->dwMtu, row->dwSpeed );
293 for (j = 0; j < row->dwPhysAddrLen; j++)
294 printf( " %02x", row->bPhysAddr[j] );
295 printf( "\n" );
296 trace( " in: bytes %u upkts %u nupkts %u disc %u err %u unk %u\n",
297 row->dwInOctets, row->dwInUcastPkts, row->dwInNUcastPkts,
298 row->dwInDiscards, row->dwInErrors, row->dwInUnknownProtos );
299 trace( " out: bytes %u upkts %u nupkts %u disc %u err %u\n",
300 row->dwOutOctets, row->dwOutUcastPkts, row->dwOutNUcastPkts,
301 row->dwOutDiscards, row->dwOutErrors );
304 HeapFree(GetProcessHeap(), 0, buf);
309 static void testGetIpForwardTable(void)
311 if (gGetIpForwardTable) {
312 DWORD apiReturn;
313 ULONG dwSize = 0;
315 apiReturn = gGetIpForwardTable(NULL, NULL, FALSE);
316 if (apiReturn == ERROR_NOT_SUPPORTED) {
317 skip("GetIpForwardTable is not supported\n");
318 return;
320 ok(apiReturn == ERROR_INVALID_PARAMETER,
321 "GetIpForwardTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
322 apiReturn);
323 apiReturn = gGetIpForwardTable(NULL, &dwSize, FALSE);
324 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
325 "GetIpForwardTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
326 apiReturn);
327 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
328 PMIB_IPFORWARDTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
330 apiReturn = gGetIpForwardTable(buf, &dwSize, FALSE);
331 ok(apiReturn == NO_ERROR,
332 "GetIpForwardTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
333 apiReturn);
335 if (apiReturn == NO_ERROR && winetest_debug > 1)
337 DWORD i;
339 trace( "IP forward table: %u entries\n", buf->dwNumEntries );
340 for (i = 0; i < buf->dwNumEntries; i++)
342 char buffer[40];
343 sprintf( buffer, "dest %s", ntoa( buf->table[i].dwForwardDest ));
344 sprintf( buffer + strlen(buffer), " mask %s", ntoa( buf->table[i].dwForwardMask ));
345 trace( "%u: %s gw %s if %u type %u\n", i, buffer,
346 ntoa( buf->table[i].dwForwardNextHop ),
347 buf->table[i].dwForwardIfIndex, buf->table[i].dwForwardType );
350 HeapFree(GetProcessHeap(), 0, buf);
355 static void testGetIpNetTable(void)
357 if (gGetIpNetTable) {
358 DWORD apiReturn;
359 ULONG dwSize = 0;
361 apiReturn = gGetIpNetTable(NULL, NULL, FALSE);
362 if (apiReturn == ERROR_NOT_SUPPORTED) {
363 skip("GetIpNetTable is not supported\n");
364 return;
366 ok(apiReturn == ERROR_INVALID_PARAMETER,
367 "GetIpNetTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
368 apiReturn);
369 apiReturn = gGetIpNetTable(NULL, &dwSize, FALSE);
370 ok(apiReturn == ERROR_NO_DATA || apiReturn == ERROR_INSUFFICIENT_BUFFER,
371 "GetIpNetTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_NO_DATA or ERROR_INSUFFICIENT_BUFFER\n",
372 apiReturn);
373 if (apiReturn == ERROR_NO_DATA)
374 ; /* empty ARP table's okay */
375 else if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
376 PMIB_IPNETTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
378 apiReturn = gGetIpNetTable(buf, &dwSize, FALSE);
379 ok(apiReturn == NO_ERROR ||
380 apiReturn == ERROR_NO_DATA, /* empty ARP table's okay */
381 "GetIpNetTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
382 apiReturn);
384 if (apiReturn == NO_ERROR && winetest_debug > 1)
386 DWORD i, j;
388 trace( "IP net table: %u entries\n", buf->dwNumEntries );
389 for (i = 0; i < buf->dwNumEntries; i++)
391 trace( "%u: idx %u type %u addr %s phys",
392 i, buf->table[i].dwIndex, buf->table[i].dwType, ntoa( buf->table[i].dwAddr ));
393 for (j = 0; j < buf->table[i].dwPhysAddrLen; j++)
394 printf( " %02x", buf->table[i].bPhysAddr[j] );
395 printf( "\n" );
398 HeapFree(GetProcessHeap(), 0, buf);
403 static void testGetIcmpStatistics(void)
405 if (gGetIcmpStatistics) {
406 DWORD apiReturn;
407 MIB_ICMP stats;
409 /* Crashes on Vista */
410 if (0) {
411 apiReturn = gGetIcmpStatistics(NULL);
412 if (apiReturn == ERROR_NOT_SUPPORTED)
413 return;
414 ok(apiReturn == ERROR_INVALID_PARAMETER,
415 "GetIcmpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
416 apiReturn);
419 apiReturn = gGetIcmpStatistics(&stats);
420 if (apiReturn == ERROR_NOT_SUPPORTED)
422 skip("GetIcmpStatistics is not supported\n");
423 return;
425 ok(apiReturn == NO_ERROR,
426 "GetIcmpStatistics returned %d, expected NO_ERROR\n", apiReturn);
427 if (apiReturn == NO_ERROR && winetest_debug > 1)
429 trace( "ICMP stats: %8s %8s\n", "in", "out" );
430 trace( " dwMsgs: %8u %8u\n", stats.stats.icmpInStats.dwMsgs, stats.stats.icmpOutStats.dwMsgs );
431 trace( " dwErrors: %8u %8u\n", stats.stats.icmpInStats.dwErrors, stats.stats.icmpOutStats.dwErrors );
432 trace( " dwDestUnreachs: %8u %8u\n", stats.stats.icmpInStats.dwDestUnreachs, stats.stats.icmpOutStats.dwDestUnreachs );
433 trace( " dwTimeExcds: %8u %8u\n", stats.stats.icmpInStats.dwTimeExcds, stats.stats.icmpOutStats.dwTimeExcds );
434 trace( " dwParmProbs: %8u %8u\n", stats.stats.icmpInStats.dwParmProbs, stats.stats.icmpOutStats.dwParmProbs );
435 trace( " dwSrcQuenchs: %8u %8u\n", stats.stats.icmpInStats.dwSrcQuenchs, stats.stats.icmpOutStats.dwSrcQuenchs );
436 trace( " dwRedirects: %8u %8u\n", stats.stats.icmpInStats.dwRedirects, stats.stats.icmpOutStats.dwRedirects );
437 trace( " dwEchos: %8u %8u\n", stats.stats.icmpInStats.dwEchos, stats.stats.icmpOutStats.dwEchos );
438 trace( " dwEchoReps: %8u %8u\n", stats.stats.icmpInStats.dwEchoReps, stats.stats.icmpOutStats.dwEchoReps );
439 trace( " dwTimestamps: %8u %8u\n", stats.stats.icmpInStats.dwTimestamps, stats.stats.icmpOutStats.dwTimestamps );
440 trace( " dwTimestampReps: %8u %8u\n", stats.stats.icmpInStats.dwTimestampReps, stats.stats.icmpOutStats.dwTimestampReps );
441 trace( " dwAddrMasks: %8u %8u\n", stats.stats.icmpInStats.dwAddrMasks, stats.stats.icmpOutStats.dwAddrMasks );
442 trace( " dwAddrMaskReps: %8u %8u\n", stats.stats.icmpInStats.dwAddrMaskReps, stats.stats.icmpOutStats.dwAddrMaskReps );
447 static void testGetIpStatistics(void)
449 if (gGetIpStatistics) {
450 DWORD apiReturn;
451 MIB_IPSTATS stats;
453 apiReturn = gGetIpStatistics(NULL);
454 if (apiReturn == ERROR_NOT_SUPPORTED) {
455 skip("GetIpStatistics is not supported\n");
456 return;
458 ok(apiReturn == ERROR_INVALID_PARAMETER,
459 "GetIpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
460 apiReturn);
461 apiReturn = gGetIpStatistics(&stats);
462 ok(apiReturn == NO_ERROR,
463 "GetIpStatistics returned %d, expected NO_ERROR\n", apiReturn);
464 if (apiReturn == NO_ERROR && winetest_debug > 1)
466 trace( "IP stats:\n" );
467 trace( " dwForwarding: %u\n", stats.dwForwarding );
468 trace( " dwDefaultTTL: %u\n", stats.dwDefaultTTL );
469 trace( " dwInReceives: %u\n", stats.dwInReceives );
470 trace( " dwInHdrErrors: %u\n", stats.dwInHdrErrors );
471 trace( " dwInAddrErrors: %u\n", stats.dwInAddrErrors );
472 trace( " dwForwDatagrams: %u\n", stats.dwForwDatagrams );
473 trace( " dwInUnknownProtos: %u\n", stats.dwInUnknownProtos );
474 trace( " dwInDiscards: %u\n", stats.dwInDiscards );
475 trace( " dwInDelivers: %u\n", stats.dwInDelivers );
476 trace( " dwOutRequests: %u\n", stats.dwOutRequests );
477 trace( " dwRoutingDiscards: %u\n", stats.dwRoutingDiscards );
478 trace( " dwOutDiscards: %u\n", stats.dwOutDiscards );
479 trace( " dwOutNoRoutes: %u\n", stats.dwOutNoRoutes );
480 trace( " dwReasmTimeout: %u\n", stats.dwReasmTimeout );
481 trace( " dwReasmReqds: %u\n", stats.dwReasmReqds );
482 trace( " dwReasmOks: %u\n", stats.dwReasmOks );
483 trace( " dwReasmFails: %u\n", stats.dwReasmFails );
484 trace( " dwFragOks: %u\n", stats.dwFragOks );
485 trace( " dwFragFails: %u\n", stats.dwFragFails );
486 trace( " dwFragCreates: %u\n", stats.dwFragCreates );
487 trace( " dwNumIf: %u\n", stats.dwNumIf );
488 trace( " dwNumAddr: %u\n", stats.dwNumAddr );
489 trace( " dwNumRoutes: %u\n", stats.dwNumRoutes );
494 static void testGetTcpStatistics(void)
496 if (gGetTcpStatistics) {
497 DWORD apiReturn;
498 MIB_TCPSTATS stats;
500 apiReturn = gGetTcpStatistics(NULL);
501 if (apiReturn == ERROR_NOT_SUPPORTED) {
502 skip("GetTcpStatistics is not supported\n");
503 return;
505 ok(apiReturn == ERROR_INVALID_PARAMETER,
506 "GetTcpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
507 apiReturn);
508 apiReturn = gGetTcpStatistics(&stats);
509 ok(apiReturn == NO_ERROR,
510 "GetTcpStatistics returned %d, expected NO_ERROR\n", apiReturn);
511 if (apiReturn == NO_ERROR && winetest_debug > 1)
513 trace( "TCP stats:\n" );
514 trace( " dwRtoAlgorithm: %u\n", stats.dwRtoAlgorithm );
515 trace( " dwRtoMin: %u\n", stats.dwRtoMin );
516 trace( " dwRtoMax: %u\n", stats.dwRtoMax );
517 trace( " dwMaxConn: %u\n", stats.dwMaxConn );
518 trace( " dwActiveOpens: %u\n", stats.dwActiveOpens );
519 trace( " dwPassiveOpens: %u\n", stats.dwPassiveOpens );
520 trace( " dwAttemptFails: %u\n", stats.dwAttemptFails );
521 trace( " dwEstabResets: %u\n", stats.dwEstabResets );
522 trace( " dwCurrEstab: %u\n", stats.dwCurrEstab );
523 trace( " dwInSegs: %u\n", stats.dwInSegs );
524 trace( " dwOutSegs: %u\n", stats.dwOutSegs );
525 trace( " dwRetransSegs: %u\n", stats.dwRetransSegs );
526 trace( " dwInErrs: %u\n", stats.dwInErrs );
527 trace( " dwOutRsts: %u\n", stats.dwOutRsts );
528 trace( " dwNumConns: %u\n", stats.dwNumConns );
533 static void testGetUdpStatistics(void)
535 if (gGetUdpStatistics) {
536 DWORD apiReturn;
537 MIB_UDPSTATS stats;
539 apiReturn = gGetUdpStatistics(NULL);
540 if (apiReturn == ERROR_NOT_SUPPORTED) {
541 skip("GetUdpStatistics is not supported\n");
542 return;
544 ok(apiReturn == ERROR_INVALID_PARAMETER,
545 "GetUdpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
546 apiReturn);
547 apiReturn = gGetUdpStatistics(&stats);
548 ok(apiReturn == NO_ERROR,
549 "GetUdpStatistics returned %d, expected NO_ERROR\n", apiReturn);
550 if (apiReturn == NO_ERROR && winetest_debug > 1)
552 trace( "UDP stats:\n" );
553 trace( " dwInDatagrams: %u\n", stats.dwInDatagrams );
554 trace( " dwNoPorts: %u\n", stats.dwNoPorts );
555 trace( " dwInErrors: %u\n", stats.dwInErrors );
556 trace( " dwOutDatagrams: %u\n", stats.dwOutDatagrams );
557 trace( " dwNumAddrs: %u\n", stats.dwNumAddrs );
562 static void testGetTcpTable(void)
564 if (gGetTcpTable) {
565 DWORD apiReturn;
566 ULONG dwSize = 0;
568 apiReturn = gGetTcpTable(NULL, &dwSize, FALSE);
569 if (apiReturn == ERROR_NOT_SUPPORTED) {
570 skip("GetTcpTable is not supported\n");
571 return;
573 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER ||
574 broken(apiReturn == ERROR_NO_DATA), /* win95 */
575 "GetTcpTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
576 apiReturn);
577 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
578 PMIB_TCPTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
580 apiReturn = gGetTcpTable(buf, &dwSize, FALSE);
581 ok(apiReturn == NO_ERROR,
582 "GetTcpTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
583 apiReturn);
585 if (apiReturn == NO_ERROR && winetest_debug > 1)
587 DWORD i;
588 trace( "TCP table: %u entries\n", buf->dwNumEntries );
589 for (i = 0; i < buf->dwNumEntries; i++)
591 char buffer[40];
592 sprintf( buffer, "local %s:%u",
593 ntoa(buf->table[i].dwLocalAddr), ntohs(buf->table[i].dwLocalPort) );
594 trace( "%u: %s remote %s:%u state %u\n",
595 i, buffer, ntoa( buf->table[i].dwRemoteAddr ),
596 ntohs(buf->table[i].dwRemotePort), buf->table[i].dwState );
599 HeapFree(GetProcessHeap(), 0, buf);
604 static void testGetUdpTable(void)
606 if (gGetUdpTable) {
607 DWORD apiReturn;
608 ULONG dwSize = 0;
610 apiReturn = gGetUdpTable(NULL, &dwSize, FALSE);
611 if (apiReturn == ERROR_NOT_SUPPORTED) {
612 skip("GetUdpTable is not supported\n");
613 return;
615 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
616 "GetUdpTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
617 apiReturn);
618 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
619 PMIB_UDPTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
621 apiReturn = gGetUdpTable(buf, &dwSize, FALSE);
622 ok(apiReturn == NO_ERROR,
623 "GetUdpTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
624 apiReturn);
626 if (apiReturn == NO_ERROR && winetest_debug > 1)
628 DWORD i;
629 trace( "UDP table: %u entries\n", buf->dwNumEntries );
630 for (i = 0; i < buf->dwNumEntries; i++)
631 trace( "%u: %s:%u\n",
632 i, ntoa( buf->table[i].dwLocalAddr ), ntohs(buf->table[i].dwLocalPort) );
634 HeapFree(GetProcessHeap(), 0, buf);
640 still-to-be-tested NT4-onward functions:
641 CreateIpForwardEntry
642 DeleteIpForwardEntry
643 CreateIpNetEntry
644 DeleteIpNetEntry
645 GetFriendlyIfIndex
646 GetRTTAndHopCount
647 SetIfEntry
648 SetIpForwardEntry
649 SetIpNetEntry
650 SetIpStatistics
651 SetIpTTL
652 SetTcpEntry
654 static void testWinNT4Functions(void)
656 testGetNumberOfInterfaces();
657 testGetIpAddrTable();
658 testGetIfTable();
659 testGetIpForwardTable();
660 testGetIpNetTable();
661 testGetIcmpStatistics();
662 testGetIpStatistics();
663 testGetTcpStatistics();
664 testGetUdpStatistics();
665 testGetTcpTable();
666 testGetUdpTable();
669 static void testGetInterfaceInfo(void)
671 if (gGetInterfaceInfo) {
672 DWORD apiReturn;
673 ULONG len = 0;
675 apiReturn = gGetInterfaceInfo(NULL, NULL);
676 if (apiReturn == ERROR_NOT_SUPPORTED) {
677 skip("GetInterfaceInfo is not supported\n");
678 return;
680 ok(apiReturn == ERROR_INVALID_PARAMETER,
681 "GetInterfaceInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
682 apiReturn);
683 apiReturn = gGetInterfaceInfo(NULL, &len);
684 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
685 "GetInterfaceInfo returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
686 apiReturn);
687 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
688 PIP_INTERFACE_INFO buf = HeapAlloc(GetProcessHeap(), 0, len);
690 apiReturn = gGetInterfaceInfo(buf, &len);
691 ok(apiReturn == NO_ERROR,
692 "GetInterfaceInfo(buf, &dwSize) returned %d, expected NO_ERROR\n",
693 apiReturn);
694 HeapFree(GetProcessHeap(), 0, buf);
699 static void testGetAdaptersInfo(void)
701 if (gGetAdaptersInfo) {
702 DWORD apiReturn;
703 ULONG len = 0;
705 apiReturn = gGetAdaptersInfo(NULL, NULL);
706 if (apiReturn == ERROR_NOT_SUPPORTED) {
707 skip("GetAdaptersInfo is not supported\n");
708 return;
710 ok(apiReturn == ERROR_INVALID_PARAMETER,
711 "GetAdaptersInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
712 apiReturn);
713 apiReturn = gGetAdaptersInfo(NULL, &len);
714 ok(apiReturn == ERROR_NO_DATA || apiReturn == ERROR_BUFFER_OVERFLOW,
715 "GetAdaptersInfo returned %d, expected ERROR_NO_DATA or ERROR_BUFFER_OVERFLOW\n",
716 apiReturn);
717 if (apiReturn == ERROR_NO_DATA)
718 ; /* no adapter's, that's okay */
719 else if (apiReturn == ERROR_BUFFER_OVERFLOW) {
720 PIP_ADAPTER_INFO buf = HeapAlloc(GetProcessHeap(), 0, len);
722 apiReturn = gGetAdaptersInfo(buf, &len);
723 ok(apiReturn == NO_ERROR,
724 "GetAdaptersInfo(buf, &dwSize) returned %d, expected NO_ERROR\n",
725 apiReturn);
726 HeapFree(GetProcessHeap(), 0, buf);
731 static void testGetNetworkParams(void)
733 if (gGetNetworkParams) {
734 DWORD apiReturn;
735 ULONG len = 0;
737 apiReturn = gGetNetworkParams(NULL, NULL);
738 if (apiReturn == ERROR_NOT_SUPPORTED) {
739 skip("GetNetworkParams is not supported\n");
740 return;
742 ok(apiReturn == ERROR_INVALID_PARAMETER,
743 "GetNetworkParams returned %d, expected ERROR_INVALID_PARAMETER\n",
744 apiReturn);
745 apiReturn = gGetNetworkParams(NULL, &len);
746 ok(apiReturn == ERROR_BUFFER_OVERFLOW,
747 "GetNetworkParams returned %d, expected ERROR_BUFFER_OVERFLOW\n",
748 apiReturn);
749 if (apiReturn == ERROR_BUFFER_OVERFLOW) {
750 PFIXED_INFO buf = HeapAlloc(GetProcessHeap(), 0, len);
752 apiReturn = gGetNetworkParams(buf, &len);
753 ok(apiReturn == NO_ERROR,
754 "GetNetworkParams(buf, &dwSize) returned %d, expected NO_ERROR\n",
755 apiReturn);
756 HeapFree(GetProcessHeap(), 0, buf);
762 still-to-be-tested 98-onward functions:
763 GetBestInterface
764 GetBestRoute
765 IpReleaseAddress
766 IpRenewAddress
768 static void testWin98Functions(void)
770 testGetInterfaceInfo();
771 testGetAdaptersInfo();
772 testGetNetworkParams();
775 static void testGetPerAdapterInfo(void)
777 DWORD ret, needed;
778 void *buffer;
780 if (!gGetPerAdapterInfo) return;
781 ret = gGetPerAdapterInfo(1, NULL, NULL);
782 if (ret == ERROR_NOT_SUPPORTED) {
783 skip("GetPerAdapterInfo is not supported\n");
784 return;
786 ok( ret == ERROR_INVALID_PARAMETER, "got %u instead of ERROR_INVALID_PARAMETER\n", ret );
787 needed = 0xdeadbeef;
788 ret = gGetPerAdapterInfo(1, NULL, &needed);
789 if (ret == ERROR_NO_DATA) return; /* no such adapter */
790 ok( ret == ERROR_BUFFER_OVERFLOW, "got %u instead of ERROR_BUFFER_OVERFLOW\n", ret );
791 ok( needed != 0xdeadbeef, "needed not set\n" );
792 buffer = HeapAlloc( GetProcessHeap(), 0, needed );
793 ret = gGetPerAdapterInfo(1, buffer, &needed);
794 ok( ret == NO_ERROR, "got %u instead of NO_ERROR\n", ret );
795 HeapFree( GetProcessHeap(), 0, buffer );
799 still-to-be-tested 2K-onward functions:
800 AddIPAddress
801 CreateProxyArpEntry
802 DeleteIPAddress
803 DeleteProxyArpEntry
804 EnableRouter
805 FlushIpNetTable
806 GetAdapterIndex
807 NotifyAddrChange
808 NotifyRouteChange
809 SendARP
810 UnenableRouter
812 static void testWin2KFunctions(void)
814 testGetPerAdapterInfo();
817 static void test_GetAdaptersAddresses(void)
819 ULONG ret, size;
820 IP_ADAPTER_ADDRESSES *aa;
821 IP_ADAPTER_UNICAST_ADDRESS *ua;
823 if (!gGetAdaptersAddresses)
825 win_skip("GetAdaptersAddresses not present\n");
826 return;
829 ret = gGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, NULL);
830 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", ret);
832 ret = gGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
833 ok(ret == ERROR_BUFFER_OVERFLOW, "expected ERROR_BUFFER_OVERFLOW, got %u\n", ret);
834 if (ret != ERROR_BUFFER_OVERFLOW) return;
836 aa = HeapAlloc(GetProcessHeap(), 0, size);
837 ret = gGetAdaptersAddresses(AF_UNSPEC, 0, NULL, aa, &size);
838 ok(!ret, "expected ERROR_SUCCESS got %u\n", ret);
840 while (!ret && winetest_debug > 1 && aa)
842 trace("Length: %u\n", aa->Length);
843 trace("IfIndex: %u\n", aa->IfIndex);
844 trace("Next: %p\n", aa->Next);
845 trace("AdapterName: %s\n", aa->AdapterName);
846 trace("FirstUnicastAddress: %p\n", aa->FirstUnicastAddress);
847 ua = aa->FirstUnicastAddress;
848 while (ua)
850 trace("\tLength: %u\n", ua->Length);
851 trace("\tFlags: 0x%08x\n", ua->Flags);
852 trace("\tNext: %p\n", ua->Next);
853 trace("\tAddress.lpSockaddr: %p\n", ua->Address.lpSockaddr);
854 trace("\tAddress.iSockaddrLength: %d\n", ua->Address.iSockaddrLength);
855 trace("\tPrefixOrigin: %u\n", ua->PrefixOrigin);
856 trace("\tSuffixOrigin: %u\n", ua->SuffixOrigin);
857 trace("\tDadState: %u\n", ua->DadState);
858 trace("\tValidLifetime: 0x%08x\n", ua->ValidLifetime);
859 trace("\tPreferredLifetime: 0x%08x\n", ua->PreferredLifetime);
860 trace("\tLeaseLifetime: 0x%08x\n", ua->LeaseLifetime);
861 trace("\n");
862 ua = ua->Next;
864 trace("FirstAnycastAddress: %p\n", aa->FirstAnycastAddress);
865 trace("FirstMulticastAddress: %p\n", aa->FirstMulticastAddress);
866 trace("FirstDnsServerAddress: %p\n", aa->FirstDnsServerAddress);
867 trace("DnsSuffix: %p\n", aa->DnsSuffix);
868 trace("Description: %p\n", aa->Description);
869 trace("FriendlyName: %p\n", aa->FriendlyName);
870 trace("PhysicalAddress: %02x\n", aa->PhysicalAddress[0]);
871 trace("PhysicalAddressLength: %u\n", aa->PhysicalAddressLength);
872 trace("Flags: 0x%08x\n", aa->Flags);
873 trace("Mtu: %u\n", aa->Mtu);
874 trace("IfType: %u\n", aa->IfType);
875 trace("OperStatus: %u\n", aa->OperStatus);
876 trace("\n");
877 aa = aa->Next;
879 HeapFree(GetProcessHeap(), 0, aa);
882 START_TEST(iphlpapi)
885 loadIPHlpApi();
886 if (hLibrary) {
887 testWin98OnlyFunctions();
888 testWinNT4Functions();
889 testWin98Functions();
890 testWin2KFunctions();
891 test_GetAdaptersAddresses();
892 freeIPHlpApi();