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.
43 #include "wine/test.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");
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)
131 gGetNumberOfInterfaces
= NULL
;
132 gGetIpAddrTable
= NULL
;
134 gGetFriendlyIfIndex
= 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
;
147 FreeLibrary(hLibrary
);
152 /* replacement for inet_ntoa */
153 static const char *ntoa( DWORD ip
)
155 static char buffer
[40];
158 sprintf( buffer
, "%u.%u.%u.%u", (ip
>> 24) & 0xff, (ip
>> 16) & 0xff, (ip
>> 8) & 0xff, ip
& 0xff );
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 */
177 apiReturn
= gGetNumberOfInterfaces(NULL
), numInterfaces
;
178 if (apiReturn
== ERROR_NOT_SUPPORTED
)
180 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
181 "GetNumberOfInterfaces(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
185 apiReturn
= gGetNumberOfInterfaces(&numInterfaces
);
186 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
187 skip("GetNumberOfInterfaces is not supported\n");
190 ok(apiReturn
== NO_ERROR
,
191 "GetNumberOfInterfaces returned %d, expected 0\n", apiReturn
);
195 static void testGetIfEntry(DWORD index
)
201 memset(&row
, 0, sizeof(row
));
202 apiReturn
= gGetIfEntry(NULL
);
203 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
204 skip("GetIfEntry is not supported\n");
207 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
208 "GetIfEntry(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
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",
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
) {
229 apiReturn
= gGetIpAddrTable(NULL
, NULL
, FALSE
);
230 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
231 skip("GetIpAddrTable is not supported\n");
234 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
235 "GetIpAddrTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
237 apiReturn
= gGetIpAddrTable(NULL
, &dwSize
, FALSE
);
238 ok(apiReturn
== ERROR_INSUFFICIENT_BUFFER
,
239 "GetIpAddrTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
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",
248 if (apiReturn
== NO_ERROR
&& buf
->dwNumEntries
)
249 testGetIfEntry(buf
->table
[0].dwIndex
);
250 HeapFree(GetProcessHeap(), 0, buf
);
255 static void testGetIfTable(void)
261 apiReturn
= gGetIfTable(NULL
, NULL
, FALSE
);
262 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
263 skip("GetIfTable is not supported\n");
266 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
267 "GetIfTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
269 apiReturn
= gGetIfTable(NULL
, &dwSize
, FALSE
);
270 ok(apiReturn
== ERROR_INSUFFICIENT_BUFFER
,
271 "GetIfTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
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",
281 if (apiReturn
== NO_ERROR
&& winetest_debug
> 1)
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
] );
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
) {
315 apiReturn
= gGetIpForwardTable(NULL
, NULL
, FALSE
);
316 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
317 skip("GetIpForwardTable is not supported\n");
320 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
321 "GetIpForwardTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
323 apiReturn
= gGetIpForwardTable(NULL
, &dwSize
, FALSE
);
324 ok(apiReturn
== ERROR_INSUFFICIENT_BUFFER
,
325 "GetIpForwardTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
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",
335 if (apiReturn
== NO_ERROR
&& winetest_debug
> 1)
339 trace( "IP forward table: %u entries\n", buf
->dwNumEntries
);
340 for (i
= 0; i
< buf
->dwNumEntries
; i
++)
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
) {
361 apiReturn
= gGetIpNetTable(NULL
, NULL
, FALSE
);
362 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
363 skip("GetIpNetTable is not supported\n");
366 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
367 "GetIpNetTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
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",
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",
384 if (apiReturn
== NO_ERROR
&& winetest_debug
> 1)
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
] );
398 HeapFree(GetProcessHeap(), 0, buf
);
403 static void testGetIcmpStatistics(void)
405 if (gGetIcmpStatistics
) {
409 /* Crashes on Vista */
411 apiReturn
= gGetIcmpStatistics(NULL
);
412 if (apiReturn
== ERROR_NOT_SUPPORTED
)
414 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
415 "GetIcmpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
419 apiReturn
= gGetIcmpStatistics(&stats
);
420 if (apiReturn
== ERROR_NOT_SUPPORTED
)
422 skip("GetIcmpStatistics is not supported\n");
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
) {
453 apiReturn
= gGetIpStatistics(NULL
);
454 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
455 skip("GetIpStatistics is not supported\n");
458 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
459 "GetIpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
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
) {
500 apiReturn
= gGetTcpStatistics(NULL
);
501 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
502 skip("GetTcpStatistics is not supported\n");
505 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
506 "GetTcpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
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
) {
539 apiReturn
= gGetUdpStatistics(NULL
);
540 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
541 skip("GetUdpStatistics is not supported\n");
544 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
545 "GetUdpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
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)
568 apiReturn
= gGetTcpTable(NULL
, &dwSize
, FALSE
);
569 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
570 skip("GetTcpTable is not supported\n");
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",
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",
585 if (apiReturn
== NO_ERROR
&& winetest_debug
> 1)
588 trace( "TCP table: %u entries\n", buf
->dwNumEntries
);
589 for (i
= 0; i
< buf
->dwNumEntries
; i
++)
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)
610 apiReturn
= gGetUdpTable(NULL
, &dwSize
, FALSE
);
611 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
612 skip("GetUdpTable is not supported\n");
615 ok(apiReturn
== ERROR_INSUFFICIENT_BUFFER
,
616 "GetUdpTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
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",
626 if (apiReturn
== NO_ERROR
&& winetest_debug
> 1)
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:
654 static void testWinNT4Functions(void)
656 testGetNumberOfInterfaces();
657 testGetIpAddrTable();
659 testGetIpForwardTable();
661 testGetIcmpStatistics();
662 testGetIpStatistics();
663 testGetTcpStatistics();
664 testGetUdpStatistics();
669 static void testGetInterfaceInfo(void)
671 if (gGetInterfaceInfo
) {
675 apiReturn
= gGetInterfaceInfo(NULL
, NULL
);
676 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
677 skip("GetInterfaceInfo is not supported\n");
680 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
681 "GetInterfaceInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
683 apiReturn
= gGetInterfaceInfo(NULL
, &len
);
684 ok(apiReturn
== ERROR_INSUFFICIENT_BUFFER
,
685 "GetInterfaceInfo returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
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",
694 HeapFree(GetProcessHeap(), 0, buf
);
699 static void testGetAdaptersInfo(void)
701 if (gGetAdaptersInfo
) {
705 apiReturn
= gGetAdaptersInfo(NULL
, NULL
);
706 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
707 skip("GetAdaptersInfo is not supported\n");
710 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
711 "GetAdaptersInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
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",
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",
726 HeapFree(GetProcessHeap(), 0, buf
);
731 static void testGetNetworkParams(void)
733 if (gGetNetworkParams
) {
737 apiReturn
= gGetNetworkParams(NULL
, NULL
);
738 if (apiReturn
== ERROR_NOT_SUPPORTED
) {
739 skip("GetNetworkParams is not supported\n");
742 ok(apiReturn
== ERROR_INVALID_PARAMETER
,
743 "GetNetworkParams returned %d, expected ERROR_INVALID_PARAMETER\n",
745 apiReturn
= gGetNetworkParams(NULL
, &len
);
746 ok(apiReturn
== ERROR_BUFFER_OVERFLOW
,
747 "GetNetworkParams returned %d, expected ERROR_BUFFER_OVERFLOW\n",
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",
756 HeapFree(GetProcessHeap(), 0, buf
);
762 still-to-be-tested 98-onward functions:
768 static DWORD CALLBACK
testWin98Functions(void *p
)
770 testGetInterfaceInfo();
771 testGetAdaptersInfo();
772 testGetNetworkParams();
776 static void testGetPerAdapterInfo(void)
781 if (!gGetPerAdapterInfo
) return;
782 ret
= gGetPerAdapterInfo(1, NULL
, NULL
);
783 if (ret
== ERROR_NOT_SUPPORTED
) {
784 skip("GetPerAdapterInfo is not supported\n");
787 ok( ret
== ERROR_INVALID_PARAMETER
, "got %u instead of ERROR_INVALID_PARAMETER\n", ret
);
789 ret
= gGetPerAdapterInfo(1, NULL
, &needed
);
790 if (ret
== ERROR_NO_DATA
) return; /* no such adapter */
791 ok( ret
== ERROR_BUFFER_OVERFLOW
, "got %u instead of ERROR_BUFFER_OVERFLOW\n", ret
);
792 ok( needed
!= 0xdeadbeef, "needed not set\n" );
793 buffer
= HeapAlloc( GetProcessHeap(), 0, needed
);
794 ret
= gGetPerAdapterInfo(1, buffer
, &needed
);
795 ok( ret
== NO_ERROR
, "got %u instead of NO_ERROR\n", ret
);
796 HeapFree( GetProcessHeap(), 0, buffer
);
800 still-to-be-tested 2K-onward functions:
813 static void testWin2KFunctions(void)
815 testGetPerAdapterInfo();
818 static void test_GetAdaptersAddresses(void)
821 IP_ADAPTER_ADDRESSES
*aa
;
822 IP_ADAPTER_UNICAST_ADDRESS
*ua
;
824 if (!gGetAdaptersAddresses
)
826 win_skip("GetAdaptersAddresses not present\n");
830 ret
= gGetAdaptersAddresses(AF_UNSPEC
, 0, NULL
, NULL
, NULL
);
831 ok(ret
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER got %u\n", ret
);
834 ret
= gGetAdaptersAddresses(AF_UNSPEC
, 0, NULL
, NULL
, &size
);
835 ok(ret
== ERROR_BUFFER_OVERFLOW
, "expected ERROR_BUFFER_OVERFLOW, got %u\n", ret
);
836 if (ret
!= ERROR_BUFFER_OVERFLOW
) return;
838 aa
= HeapAlloc(GetProcessHeap(), 0, size
);
839 ret
= gGetAdaptersAddresses(AF_UNSPEC
, 0, NULL
, aa
, &size
);
840 ok(!ret
, "expected ERROR_SUCCESS got %u\n", ret
);
842 while (!ret
&& winetest_debug
> 1 && aa
)
844 trace("Length: %u\n", S(U(*aa
)).Length
);
845 trace("IfIndex: %u\n", S(U(*aa
)).IfIndex
);
846 trace("Next: %p\n", aa
->Next
);
847 trace("AdapterName: %s\n", aa
->AdapterName
);
848 trace("FirstUnicastAddress: %p\n", aa
->FirstUnicastAddress
);
849 ua
= aa
->FirstUnicastAddress
;
852 trace("\tLength: %u\n", S(U(*ua
)).Length
);
853 trace("\tFlags: 0x%08x\n", S(U(*ua
)).Flags
);
854 trace("\tNext: %p\n", ua
->Next
);
855 trace("\tAddress.lpSockaddr: %p\n", ua
->Address
.lpSockaddr
);
856 trace("\tAddress.iSockaddrLength: %d\n", ua
->Address
.iSockaddrLength
);
857 trace("\tPrefixOrigin: %u\n", ua
->PrefixOrigin
);
858 trace("\tSuffixOrigin: %u\n", ua
->SuffixOrigin
);
859 trace("\tDadState: %u\n", ua
->DadState
);
860 trace("\tValidLifetime: 0x%08x\n", ua
->ValidLifetime
);
861 trace("\tPreferredLifetime: 0x%08x\n", ua
->PreferredLifetime
);
862 trace("\tLeaseLifetime: 0x%08x\n", ua
->LeaseLifetime
);
866 trace("FirstAnycastAddress: %p\n", aa
->FirstAnycastAddress
);
867 trace("FirstMulticastAddress: %p\n", aa
->FirstMulticastAddress
);
868 trace("FirstDnsServerAddress: %p\n", aa
->FirstDnsServerAddress
);
869 trace("DnsSuffix: %p\n", aa
->DnsSuffix
);
870 trace("Description: %p\n", aa
->Description
);
871 trace("FriendlyName: %p\n", aa
->FriendlyName
);
872 trace("PhysicalAddress: %02x\n", aa
->PhysicalAddress
[0]);
873 trace("PhysicalAddressLength: %u\n", aa
->PhysicalAddressLength
);
874 trace("Flags: 0x%08x\n", aa
->Flags
);
875 trace("Mtu: %u\n", aa
->Mtu
);
876 trace("IfType: %u\n", aa
->IfType
);
877 trace("OperStatus: %u\n", aa
->OperStatus
);
881 HeapFree(GetProcessHeap(), 0, aa
);
891 testWin98OnlyFunctions();
892 testWinNT4Functions();
894 /* run testGetXXXX in two threads at once to make sure we don't crash in that case */
895 thread
= CreateThread(NULL
, 0, testWin98Functions
, NULL
, 0, NULL
);
896 testWin98Functions(NULL
);
897 WaitForSingleObject(thread
, INFINITE
);
899 testWin2KFunctions();
900 test_GetAdaptersAddresses();