1 /*
2  * iphlpapi dll test
3  *
4  * Copyright (C) 2003 Juan Lang
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 /*
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).
28  *
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.
33  *
34  * The DomainName field of FIXED_INFO isn't NULL-terminated on Win98.
35  */
36 
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>
48 
49 #define ICMP_MINLEN 8 /* copied from dlls/iphlpapi/ip_icmp.h file */
50 
51 static HMODULE hLibrary = NULL;
52 
53 static DWORD (WINAPI *pGetNumberOfInterfaces)(PDWORD);
54 static DWORD (WINAPI *pGetIpAddrTable)(PMIB_IPADDRTABLE,PULONG,BOOL);
55 static DWORD (WINAPI *pGetIfEntry)(PMIB_IFROW);
56 static DWORD (WINAPI *pGetIfEntry2)(PMIB_IF_ROW2);
57 static DWORD (WINAPI *pGetFriendlyIfIndex)(DWORD);
58 static DWORD (WINAPI *pGetIfTable)(PMIB_IFTABLE,PULONG,BOOL);
59 static DWORD (WINAPI *pGetIfTable2)(PMIB_IF_TABLE2*);
60 static DWORD (WINAPI *pGetIpForwardTable)(PMIB_IPFORWARDTABLE,PULONG,BOOL);
61 static DWORD (WINAPI *pGetIpNetTable)(PMIB_IPNETTABLE,PULONG,BOOL);
62 static DWORD (WINAPI *pGetInterfaceInfo)(PIP_INTERFACE_INFO,PULONG);
63 static DWORD (WINAPI *pGetAdaptersInfo)(PIP_ADAPTER_INFO,PULONG);
64 static DWORD (WINAPI *pGetNetworkParams)(PFIXED_INFO,PULONG);
65 static DWORD (WINAPI *pGetIcmpStatistics)(PMIB_ICMP);
66 static DWORD (WINAPI *pGetIpStatistics)(PMIB_IPSTATS);
67 static DWORD (WINAPI *pGetTcpStatistics)(PMIB_TCPSTATS);
68 static DWORD (WINAPI *pGetUdpStatistics)(PMIB_UDPSTATS);
69 static DWORD (WINAPI *pGetIcmpStatisticsEx)(PMIB_ICMP_EX,DWORD);
70 static DWORD (WINAPI *pGetIpStatisticsEx)(PMIB_IPSTATS,DWORD);
71 static DWORD (WINAPI *pGetTcpStatisticsEx)(PMIB_TCPSTATS,DWORD);
72 static DWORD (WINAPI *pGetUdpStatisticsEx)(PMIB_UDPSTATS,DWORD);
73 static DWORD (WINAPI *pGetTcpTable)(PMIB_TCPTABLE,PDWORD,BOOL);
74 static DWORD (WINAPI *pGetUdpTable)(PMIB_UDPTABLE,PDWORD,BOOL);
75 static DWORD (WINAPI *pGetPerAdapterInfo)(ULONG,PIP_PER_ADAPTER_INFO,PULONG);
76 static DWORD (WINAPI *pGetAdaptersAddresses)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG);
77 static DWORD (WINAPI *pNotifyAddrChange)(PHANDLE,LPOVERLAPPED);
78 static BOOL  (WINAPI *pCancelIPChangeNotify)(LPOVERLAPPED);
79 static DWORD (WINAPI *pGetExtendedTcpTable)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG);
80 static DWORD (WINAPI *pGetExtendedUdpTable)(PVOID,PDWORD,BOOL,ULONG,UDP_TABLE_CLASS,ULONG);
81 static DWORD (WINAPI *pSetTcpEntry)(PMIB_TCPROW);
82 static HANDLE(WINAPI *pIcmpCreateFile)(VOID);
83 static DWORD (WINAPI *pIcmpSendEcho)(HANDLE,IPAddr,LPVOID,WORD,PIP_OPTION_INFORMATION,LPVOID,DWORD,DWORD);
84 static DWORD (WINAPI *pCreateSortedAddressPairs)(const PSOCKADDR_IN6,ULONG,const PSOCKADDR_IN6,ULONG,ULONG,
85                                                  PSOCKADDR_IN6_PAIR*,ULONG*);
86 static void (WINAPI *pFreeMibTable)(void*);
87 static DWORD (WINAPI *pConvertInterfaceGuidToLuid)(const GUID*,NET_LUID*);
88 static DWORD (WINAPI *pConvertInterfaceIndexToLuid)(NET_IFINDEX,NET_LUID*);
89 static DWORD (WINAPI *pConvertInterfaceLuidToGuid)(const NET_LUID*,GUID*);
90 static DWORD (WINAPI *pConvertInterfaceLuidToIndex)(const NET_LUID*,NET_IFINDEX*);
91 static DWORD (WINAPI *pConvertInterfaceLuidToNameW)(const NET_LUID*,WCHAR*,SIZE_T);
92 static DWORD (WINAPI *pConvertInterfaceLuidToNameA)(const NET_LUID*,char*,SIZE_T);
93 static DWORD (WINAPI *pConvertInterfaceNameToLuidA)(const char*,NET_LUID*);
94 static DWORD (WINAPI *pConvertInterfaceNameToLuidW)(const WCHAR*,NET_LUID*);
95 
loadIPHlpApi(void)96 static void loadIPHlpApi(void)
97 {
98   hLibrary = LoadLibraryA("iphlpapi.dll");
99   if (hLibrary) {
100     pGetNumberOfInterfaces = (void *)GetProcAddress(hLibrary, "GetNumberOfInterfaces");
101     pGetIpAddrTable = (void *)GetProcAddress(hLibrary, "GetIpAddrTable");
102     pGetIfEntry = (void *)GetProcAddress(hLibrary, "GetIfEntry");
103     pGetIfEntry2 = (void *)GetProcAddress(hLibrary, "GetIfEntry2");
104     pGetFriendlyIfIndex = (void *)GetProcAddress(hLibrary, "GetFriendlyIfIndex");
105     pGetIfTable = (void *)GetProcAddress(hLibrary, "GetIfTable");
106     pGetIfTable2 = (void *)GetProcAddress(hLibrary, "GetIfTable2");
107     pGetIpForwardTable = (void *)GetProcAddress(hLibrary, "GetIpForwardTable");
108     pGetIpNetTable = (void *)GetProcAddress(hLibrary, "GetIpNetTable");
109     pGetInterfaceInfo = (void *)GetProcAddress(hLibrary, "GetInterfaceInfo");
110     pGetAdaptersInfo = (void *)GetProcAddress(hLibrary, "GetAdaptersInfo");
111     pGetNetworkParams = (void *)GetProcAddress(hLibrary, "GetNetworkParams");
112     pGetIcmpStatistics = (void *)GetProcAddress(hLibrary, "GetIcmpStatistics");
113     pGetIpStatistics = (void *)GetProcAddress(hLibrary, "GetIpStatistics");
114     pGetTcpStatistics = (void *)GetProcAddress(hLibrary, "GetTcpStatistics");
115     pGetUdpStatistics = (void *)GetProcAddress(hLibrary, "GetUdpStatistics");
116     pGetIcmpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetIcmpStatisticsEx");
117     pGetIpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetIpStatisticsEx");
118     pGetTcpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetTcpStatisticsEx");
119     pGetUdpStatisticsEx = (void *)GetProcAddress(hLibrary, "GetUdpStatisticsEx");
120     pGetTcpTable = (void *)GetProcAddress(hLibrary, "GetTcpTable");
121     pGetUdpTable = (void *)GetProcAddress(hLibrary, "GetUdpTable");
122     pGetPerAdapterInfo = (void *)GetProcAddress(hLibrary, "GetPerAdapterInfo");
123     pGetAdaptersAddresses = (void *)GetProcAddress(hLibrary, "GetAdaptersAddresses");
124     pNotifyAddrChange = (void *)GetProcAddress(hLibrary, "NotifyAddrChange");
125     pCancelIPChangeNotify = (void *)GetProcAddress(hLibrary, "CancelIPChangeNotify");
126     pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable");
127     pGetExtendedUdpTable = (void *)GetProcAddress(hLibrary, "GetExtendedUdpTable");
128     pSetTcpEntry = (void *)GetProcAddress(hLibrary, "SetTcpEntry");
129     pIcmpCreateFile = (void *)GetProcAddress(hLibrary, "IcmpCreateFile");
130     pIcmpSendEcho = (void *)GetProcAddress(hLibrary, "IcmpSendEcho");
131     pCreateSortedAddressPairs = (void *)GetProcAddress(hLibrary, "CreateSortedAddressPairs");
132     pFreeMibTable = (void *)GetProcAddress(hLibrary, "FreeMibTable");
133     pConvertInterfaceGuidToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceGuidToLuid");
134     pConvertInterfaceIndexToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceIndexToLuid");
135     pConvertInterfaceLuidToGuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToGuid");
136     pConvertInterfaceLuidToIndex = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToIndex");
137     pConvertInterfaceLuidToNameA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameA");
138     pConvertInterfaceLuidToNameW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameW");
139     pConvertInterfaceNameToLuidA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidA");
140     pConvertInterfaceNameToLuidW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidW");
141   }
142 }
143 
freeIPHlpApi(void)144 static void freeIPHlpApi(void)
145 {
146     FreeLibrary(hLibrary);
147 }
148 
149 /* replacement for inet_ntoa */
ntoa(DWORD ip)150 static const char *ntoa( DWORD ip )
151 {
152     static char buffer[40];
153 
154     ip = htonl(ip);
155     sprintf( buffer, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff );
156     return buffer;
157 }
158 
debugstr_longlong(ULONGLONG ll)159 static inline const char* debugstr_longlong(ULONGLONG ll)
160 {
161     static char string[17];
162     if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
163         sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
164     else
165         sprintf(string, "%lx", (unsigned long)ll);
166     return string;
167 }
168 
169 /*
170 still-to-be-tested 98-only functions:
171 GetUniDirectionalAdapterInfo
172 */
testWin98OnlyFunctions(void)173 static void testWin98OnlyFunctions(void)
174 {
175 }
176 
testGetNumberOfInterfaces(void)177 static void testGetNumberOfInterfaces(void)
178 {
179   if (pGetNumberOfInterfaces) {
180     DWORD apiReturn, numInterfaces;
181 
182     /* Crashes on Vista */
183     if (0) {
184       apiReturn = pGetNumberOfInterfaces(NULL);
185       if (apiReturn == ERROR_NOT_SUPPORTED)
186         return;
187       ok(apiReturn == ERROR_INVALID_PARAMETER,
188        "GetNumberOfInterfaces(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
189        apiReturn);
190     }
191 
192     apiReturn = pGetNumberOfInterfaces(&numInterfaces);
193     if (apiReturn == ERROR_NOT_SUPPORTED) {
194       skip("GetNumberOfInterfaces is not supported\n");
195       return;
196     }
197     ok(apiReturn == NO_ERROR,
198      "GetNumberOfInterfaces returned %d, expected 0\n", apiReturn);
199   }
200 }
201 
testGetIfEntry(DWORD index)202 static void testGetIfEntry(DWORD index)
203 {
204   if (pGetIfEntry) {
205     DWORD apiReturn;
206     MIB_IFROW row;
207 
208     memset(&row, 0, sizeof(row));
209     apiReturn = pGetIfEntry(NULL);
210     if (apiReturn == ERROR_NOT_SUPPORTED) {
211       skip("GetIfEntry is not supported\n");
212       return;
213     }
214     ok(apiReturn == ERROR_INVALID_PARAMETER,
215      "GetIfEntry(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
216      apiReturn);
217     row.dwIndex = -1; /* hope that's always bogus! */
218     apiReturn = pGetIfEntry(&row);
219     ok(apiReturn == ERROR_INVALID_DATA ||
220      apiReturn == ERROR_FILE_NOT_FOUND /* Vista */,
221      "GetIfEntry(bogus row) returned %d, expected ERROR_INVALID_DATA or ERROR_FILE_NOT_FOUND\n",
222      apiReturn);
223     row.dwIndex = index;
224     apiReturn = pGetIfEntry(&row);
225     ok(apiReturn == NO_ERROR,
226      "GetIfEntry returned %d, expected NO_ERROR\n", apiReturn);
227   }
228 }
229 
testGetIpAddrTable(void)230 static void testGetIpAddrTable(void)
231 {
232   if (pGetIpAddrTable) {
233     DWORD apiReturn;
234     ULONG dwSize = 0;
235 
236     apiReturn = pGetIpAddrTable(NULL, NULL, FALSE);
237     if (apiReturn == ERROR_NOT_SUPPORTED) {
238       skip("GetIpAddrTable is not supported\n");
239       return;
240     }
241     ok(apiReturn == ERROR_INVALID_PARAMETER,
242      "GetIpAddrTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
243      apiReturn);
244     apiReturn = pGetIpAddrTable(NULL, &dwSize, FALSE);
245     ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
246      "GetIpAddrTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
247      apiReturn);
248     if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
249       PMIB_IPADDRTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
250 
251       apiReturn = pGetIpAddrTable(buf, &dwSize, FALSE);
252       ok(apiReturn == NO_ERROR,
253        "GetIpAddrTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
254        apiReturn);
255       if (apiReturn == NO_ERROR && buf->dwNumEntries)
256       {
257         int i;
258         testGetIfEntry(buf->table[0].dwIndex);
259         for (i = 0; i < buf->dwNumEntries; i++)
260         {
261           ok (buf->table[i].wType != 0, "Test[%d]: expected wType > 0\n", i);
262           trace("Entry[%d]: addr %s, dwIndex %u, wType 0x%x\n", i,
263                 ntoa(buf->table[i].dwAddr), buf->table[i].dwIndex, buf->table[i].wType);
264         }
265       }
266       HeapFree(GetProcessHeap(), 0, buf);
267     }
268   }
269 }
270 
testGetIfTable(void)271 static void testGetIfTable(void)
272 {
273   if (pGetIfTable) {
274     DWORD apiReturn;
275     ULONG dwSize = 0;
276 
277     apiReturn = pGetIfTable(NULL, NULL, FALSE);
278     if (apiReturn == ERROR_NOT_SUPPORTED) {
279       skip("GetIfTable is not supported\n");
280       return;
281     }
282     ok(apiReturn == ERROR_INVALID_PARAMETER,
283      "GetIfTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
284      apiReturn);
285     apiReturn = pGetIfTable(NULL, &dwSize, FALSE);
286     ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
287      "GetIfTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
288      apiReturn);
289     if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
290       PMIB_IFTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
291 
292       apiReturn = pGetIfTable(buf, &dwSize, FALSE);
293       ok(apiReturn == NO_ERROR,
294        "GetIfTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n\n",
295        apiReturn);
296 
297       if (apiReturn == NO_ERROR && winetest_debug > 1)
298       {
299           DWORD i, j;
300           char name[MAX_INTERFACE_NAME_LEN];
301 
302           trace( "interface table: %u entries\n", buf->dwNumEntries );
303           for (i = 0; i < buf->dwNumEntries; i++)
304           {
305               MIB_IFROW *row = &buf->table[i];
306               WideCharToMultiByte( CP_ACP, 0, row->wszName, -1, name, MAX_INTERFACE_NAME_LEN, NULL, NULL );
307               trace( "%u: '%s' type %u mtu %u speed %u phys",
308                      row->dwIndex, name, row->dwType, row->dwMtu, row->dwSpeed );
309               for (j = 0; j < row->dwPhysAddrLen; j++)
310                   printf( " %02x", row->bPhysAddr[j] );
311               printf( "\n" );
312               trace( "        in: bytes %u upkts %u nupkts %u disc %u err %u unk %u\n",
313                      row->dwInOctets, row->dwInUcastPkts, row->dwInNUcastPkts,
314                      row->dwInDiscards, row->dwInErrors, row->dwInUnknownProtos );
315               trace( "        out: bytes %u upkts %u nupkts %u disc %u err %u\n",
316                      row->dwOutOctets, row->dwOutUcastPkts, row->dwOutNUcastPkts,
317                      row->dwOutDiscards, row->dwOutErrors );
318           }
319       }
320       HeapFree(GetProcessHeap(), 0, buf);
321     }
322   }
323 }
324 
testGetIpForwardTable(void)325 static void testGetIpForwardTable(void)
326 {
327   if (pGetIpForwardTable) {
328     DWORD apiReturn;
329     ULONG dwSize = 0;
330 
331     apiReturn = pGetIpForwardTable(NULL, NULL, FALSE);
332     if (apiReturn == ERROR_NOT_SUPPORTED) {
333       skip("GetIpForwardTable is not supported\n");
334       return;
335     }
336     ok(apiReturn == ERROR_INVALID_PARAMETER,
337      "GetIpForwardTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
338      apiReturn);
339     apiReturn = pGetIpForwardTable(NULL, &dwSize, FALSE);
340     ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
341      "GetIpForwardTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
342      apiReturn);
343     if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
344       PMIB_IPFORWARDTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
345 
346       apiReturn = pGetIpForwardTable(buf, &dwSize, FALSE);
347       ok(apiReturn == NO_ERROR,
348        "GetIpForwardTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
349        apiReturn);
350 
351       if (apiReturn == NO_ERROR && winetest_debug > 1)
352       {
353           DWORD i;
354 
355           trace( "IP forward table: %u entries\n", buf->dwNumEntries );
356           for (i = 0; i < buf->dwNumEntries; i++)
357           {
358               char buffer[100];
359               sprintf( buffer, "dest %s", ntoa( buf->table[i].dwForwardDest ));
360               sprintf( buffer + strlen(buffer), " mask %s", ntoa( buf->table[i].dwForwardMask ));
361               trace( "%u: %s gw %s if %u type %u\n", i, buffer,
362                      ntoa( buf->table[i].dwForwardNextHop ),
363                      buf->table[i].dwForwardIfIndex, U1(buf->table[i]).dwForwardType );
364           }
365       }
366       HeapFree(GetProcessHeap(), 0, buf);
367     }
368   }
369 }
370 
testGetIpNetTable(void)371 static void testGetIpNetTable(void)
372 {
373   if (pGetIpNetTable) {
374     DWORD apiReturn;
375     ULONG dwSize = 0;
376 
377     apiReturn = pGetIpNetTable(NULL, NULL, FALSE);
378     if (apiReturn == ERROR_NOT_SUPPORTED) {
379       skip("GetIpNetTable is not supported\n");
380       return;
381     }
382     ok(apiReturn == ERROR_INVALID_PARAMETER,
383      "GetIpNetTable(NULL, NULL, FALSE) returned %d, expected ERROR_INVALID_PARAMETER\n",
384      apiReturn);
385     apiReturn = pGetIpNetTable(NULL, &dwSize, FALSE);
386     ok(apiReturn == ERROR_NO_DATA || apiReturn == ERROR_INSUFFICIENT_BUFFER,
387      "GetIpNetTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_NO_DATA or ERROR_INSUFFICIENT_BUFFER\n",
388      apiReturn);
389     if (apiReturn == ERROR_NO_DATA)
390       ; /* empty ARP table's okay */
391     else if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
392       PMIB_IPNETTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
393 
394       apiReturn = pGetIpNetTable(buf, &dwSize, FALSE);
395       ok(apiReturn == NO_ERROR ||
396          apiReturn == ERROR_NO_DATA, /* empty ARP table's okay */
397        "GetIpNetTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
398        apiReturn);
399 
400       if (apiReturn == NO_ERROR && winetest_debug > 1)
401       {
402           DWORD i, j;
403 
404           trace( "IP net table: %u entries\n", buf->dwNumEntries );
405           for (i = 0; i < buf->dwNumEntries; i++)
406           {
407               trace( "%u: idx %u type %u addr %s phys",
408                      i, buf->table[i].dwIndex, U(buf->table[i]).dwType, ntoa( buf->table[i].dwAddr ));
409               for (j = 0; j < buf->table[i].dwPhysAddrLen; j++)
410                   printf( " %02x", buf->table[i].bPhysAddr[j] );
411               printf( "\n" );
412           }
413       }
414       HeapFree(GetProcessHeap(), 0, buf);
415     }
416   }
417 }
418 
testGetIcmpStatistics(void)419 static void testGetIcmpStatistics(void)
420 {
421   if (pGetIcmpStatistics) {
422     DWORD apiReturn;
423     MIB_ICMP stats;
424 
425     /* Crashes on Vista */
426     if (0) {
427       apiReturn = pGetIcmpStatistics(NULL);
428       if (apiReturn == ERROR_NOT_SUPPORTED)
429         return;
430       ok(apiReturn == ERROR_INVALID_PARAMETER,
431        "GetIcmpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
432        apiReturn);
433     }
434 
435     apiReturn = pGetIcmpStatistics(&stats);
436     if (apiReturn == ERROR_NOT_SUPPORTED)
437     {
438       skip("GetIcmpStatistics is not supported\n");
439       return;
440     }
441     ok(apiReturn == NO_ERROR,
442      "GetIcmpStatistics returned %d, expected NO_ERROR\n", apiReturn);
443     if (apiReturn == NO_ERROR && winetest_debug > 1)
444     {
445         trace( "ICMP stats:          %8s %8s\n", "in", "out" );
446         trace( "    dwMsgs:          %8u %8u\n", stats.stats.icmpInStats.dwMsgs, stats.stats.icmpOutStats.dwMsgs );
447         trace( "    dwErrors:        %8u %8u\n", stats.stats.icmpInStats.dwErrors, stats.stats.icmpOutStats.dwErrors );
448         trace( "    dwDestUnreachs:  %8u %8u\n", stats.stats.icmpInStats.dwDestUnreachs, stats.stats.icmpOutStats.dwDestUnreachs );
449         trace( "    dwTimeExcds:     %8u %8u\n", stats.stats.icmpInStats.dwTimeExcds, stats.stats.icmpOutStats.dwTimeExcds );
450         trace( "    dwParmProbs:     %8u %8u\n", stats.stats.icmpInStats.dwParmProbs, stats.stats.icmpOutStats.dwParmProbs );
451         trace( "    dwSrcQuenchs:    %8u %8u\n", stats.stats.icmpInStats.dwSrcQuenchs, stats.stats.icmpOutStats.dwSrcQuenchs );
452         trace( "    dwRedirects:     %8u %8u\n", stats.stats.icmpInStats.dwRedirects, stats.stats.icmpOutStats.dwRedirects );
453         trace( "    dwEchos:         %8u %8u\n", stats.stats.icmpInStats.dwEchos, stats.stats.icmpOutStats.dwEchos );
454         trace( "    dwEchoReps:      %8u %8u\n", stats.stats.icmpInStats.dwEchoReps, stats.stats.icmpOutStats.dwEchoReps );
455         trace( "    dwTimestamps:    %8u %8u\n", stats.stats.icmpInStats.dwTimestamps, stats.stats.icmpOutStats.dwTimestamps );
456         trace( "    dwTimestampReps: %8u %8u\n", stats.stats.icmpInStats.dwTimestampReps, stats.stats.icmpOutStats.dwTimestampReps );
457         trace( "    dwAddrMasks:     %8u %8u\n", stats.stats.icmpInStats.dwAddrMasks, stats.stats.icmpOutStats.dwAddrMasks );
458         trace( "    dwAddrMaskReps:  %8u %8u\n", stats.stats.icmpInStats.dwAddrMaskReps, stats.stats.icmpOutStats.dwAddrMaskReps );
459     }
460   }
461 }
462 
testGetIpStatistics(void)463 static void testGetIpStatistics(void)
464 {
465   if (pGetIpStatistics) {
466     DWORD apiReturn;
467     MIB_IPSTATS stats;
468 
469     apiReturn = pGetIpStatistics(NULL);
470     if (apiReturn == ERROR_NOT_SUPPORTED) {
471       skip("GetIpStatistics is not supported\n");
472       return;
473     }
474     ok(apiReturn == ERROR_INVALID_PARAMETER,
475      "GetIpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
476      apiReturn);
477     apiReturn = pGetIpStatistics(&stats);
478     ok(apiReturn == NO_ERROR,
479       "GetIpStatistics returned %d, expected NO_ERROR\n", apiReturn);
480     if (apiReturn == NO_ERROR && winetest_debug > 1)
481     {
482         trace( "IP stats:\n" );
483         trace( "    dwForwarding:      %u\n", U(stats).dwForwarding );
484         trace( "    dwDefaultTTL:      %u\n", stats.dwDefaultTTL );
485         trace( "    dwInReceives:      %u\n", stats.dwInReceives );
486         trace( "    dwInHdrErrors:     %u\n", stats.dwInHdrErrors );
487         trace( "    dwInAddrErrors:    %u\n", stats.dwInAddrErrors );
488         trace( "    dwForwDatagrams:   %u\n", stats.dwForwDatagrams );
489         trace( "    dwInUnknownProtos: %u\n", stats.dwInUnknownProtos );
490         trace( "    dwInDiscards:      %u\n", stats.dwInDiscards );
491         trace( "    dwInDelivers:      %u\n", stats.dwInDelivers );
492         trace( "    dwOutRequests:     %u\n", stats.dwOutRequests );
493         trace( "    dwRoutingDiscards: %u\n", stats.dwRoutingDiscards );
494         trace( "    dwOutDiscards:     %u\n", stats.dwOutDiscards );
495         trace( "    dwOutNoRoutes:     %u\n", stats.dwOutNoRoutes );
496         trace( "    dwReasmTimeout:    %u\n", stats.dwReasmTimeout );
497         trace( "    dwReasmReqds:      %u\n", stats.dwReasmReqds );
498         trace( "    dwReasmOks:        %u\n", stats.dwReasmOks );
499         trace( "    dwReasmFails:      %u\n", stats.dwReasmFails );
500         trace( "    dwFragOks:         %u\n", stats.dwFragOks );
501         trace( "    dwFragFails:       %u\n", stats.dwFragFails );
502         trace( "    dwFragCreates:     %u\n", stats.dwFragCreates );
503         trace( "    dwNumIf:           %u\n", stats.dwNumIf );
504         trace( "    dwNumAddr:         %u\n", stats.dwNumAddr );
505         trace( "    dwNumRoutes:       %u\n", stats.dwNumRoutes );
506     }
507   }
508 }
509 
testGetTcpStatistics(void)510 static void testGetTcpStatistics(void)
511 {
512   if (pGetTcpStatistics) {
513     DWORD apiReturn;
514     MIB_TCPSTATS stats;
515 
516     apiReturn = pGetTcpStatistics(NULL);
517     if (apiReturn == ERROR_NOT_SUPPORTED) {
518       skip("GetTcpStatistics is not supported\n");
519       return;
520     }
521     ok(apiReturn == ERROR_INVALID_PARAMETER,
522      "GetTcpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
523      apiReturn);
524     apiReturn = pGetTcpStatistics(&stats);
525     ok(apiReturn == NO_ERROR,
526       "GetTcpStatistics returned %d, expected NO_ERROR\n", apiReturn);
527     if (apiReturn == NO_ERROR && winetest_debug > 1)
528     {
529         trace( "TCP stats:\n" );
530         trace( "    dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
531         trace( "    dwRtoMin:       %u\n", stats.dwRtoMin );
532         trace( "    dwRtoMax:       %u\n", stats.dwRtoMax );
533         trace( "    dwMaxConn:      %u\n", stats.dwMaxConn );
534         trace( "    dwActiveOpens:  %u\n", stats.dwActiveOpens );
535         trace( "    dwPassiveOpens: %u\n", stats.dwPassiveOpens );
536         trace( "    dwAttemptFails: %u\n", stats.dwAttemptFails );
537         trace( "    dwEstabResets:  %u\n", stats.dwEstabResets );
538         trace( "    dwCurrEstab:    %u\n", stats.dwCurrEstab );
539         trace( "    dwInSegs:       %u\n", stats.dwInSegs );
540         trace( "    dwOutSegs:      %u\n", stats.dwOutSegs );
541         trace( "    dwRetransSegs:  %u\n", stats.dwRetransSegs );
542         trace( "    dwInErrs:       %u\n", stats.dwInErrs );
543         trace( "    dwOutRsts:      %u\n", stats.dwOutRsts );
544         trace( "    dwNumConns:     %u\n", stats.dwNumConns );
545     }
546   }
547 }
548 
testGetUdpStatistics(void)549 static void testGetUdpStatistics(void)
550 {
551   if (pGetUdpStatistics) {
552     DWORD apiReturn;
553     MIB_UDPSTATS stats;
554 
555     apiReturn = pGetUdpStatistics(NULL);
556     if (apiReturn == ERROR_NOT_SUPPORTED) {
557       skip("GetUdpStatistics is not supported\n");
558       return;
559     }
560     ok(apiReturn == ERROR_INVALID_PARAMETER,
561      "GetUdpStatistics(NULL) returned %d, expected ERROR_INVALID_PARAMETER\n",
562      apiReturn);
563     apiReturn = pGetUdpStatistics(&stats);
564     ok(apiReturn == NO_ERROR,
565      "GetUdpStatistics returned %d, expected NO_ERROR\n", apiReturn);
566     if (apiReturn == NO_ERROR && winetest_debug > 1)
567     {
568         trace( "UDP stats:\n" );
569         trace( "    dwInDatagrams:  %u\n", stats.dwInDatagrams );
570         trace( "    dwNoPorts:      %u\n", stats.dwNoPorts );
571         trace( "    dwInErrors:     %u\n", stats.dwInErrors );
572         trace( "    dwOutDatagrams: %u\n", stats.dwOutDatagrams );
573         trace( "    dwNumAddrs:     %u\n", stats.dwNumAddrs );
574     }
575   }
576 }
577 
testGetIcmpStatisticsEx(void)578 static void testGetIcmpStatisticsEx(void)
579 {
580     DWORD apiReturn;
581     MIB_ICMP_EX stats;
582 
583     if (!pGetIcmpStatisticsEx)
584     {
585         win_skip( "GetIcmpStatisticsEx not available\n" );
586         return;
587     }
588 
589     /* Crashes on Vista */
590     if (1) {
591         apiReturn = pGetIcmpStatisticsEx(NULL, AF_INET);
592         ok(apiReturn == ERROR_INVALID_PARAMETER,
593          "GetIcmpStatisticsEx(NULL, AF_INET) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
594     }
595 
596     apiReturn = pGetIcmpStatisticsEx(&stats, AF_BAN);
597     ok(apiReturn == ERROR_INVALID_PARAMETER,
598        "GetIcmpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
599 
600     apiReturn = pGetIcmpStatisticsEx(&stats, AF_INET);
601     ok(apiReturn == NO_ERROR, "GetIcmpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
602     if (apiReturn == NO_ERROR && winetest_debug > 1)
603     {
604         INT i;
605         trace( "ICMP IPv4 Ex stats:           %8s %8s\n", "in", "out" );
606         trace( "    dwMsgs:              %8u %8u\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
607         trace( "    dwErrors:            %8u %8u\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
608         for (i = 0; i < 256; i++)
609             trace( "    rgdwTypeCount[%3i]: %8u %8u\n", i, stats.icmpInStats.rgdwTypeCount[i], stats.icmpOutStats.rgdwTypeCount[i] );
610     }
611 
612     apiReturn = pGetIcmpStatisticsEx(&stats, AF_INET6);
613     ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
614        "GetIcmpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
615     if (apiReturn == NO_ERROR && winetest_debug > 1)
616     {
617         INT i;
618         trace( "ICMP IPv6 Ex stats:           %8s %8s\n", "in", "out" );
619         trace( "    dwMsgs:              %8u %8u\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
620         trace( "    dwErrors:            %8u %8u\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
621         for (i = 0; i < 256; i++)
622             trace( "    rgdwTypeCount[%3i]: %8u %8u\n", i, stats.icmpInStats.rgdwTypeCount[i], stats.icmpOutStats.rgdwTypeCount[i] );
623     }
624 }
625 
testGetIpStatisticsEx(void)626 static void testGetIpStatisticsEx(void)
627 {
628     DWORD apiReturn;
629     MIB_IPSTATS stats;
630 
631     if (!pGetIpStatisticsEx)
632     {
633         win_skip( "GetIpStatisticsEx not available\n" );
634         return;
635     }
636 
637     apiReturn = pGetIpStatisticsEx(NULL, AF_INET);
638     ok(apiReturn == ERROR_INVALID_PARAMETER,
639        "GetIpStatisticsEx(NULL, AF_INET) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
640 
641     apiReturn = pGetIpStatisticsEx(&stats, AF_BAN);
642     ok(apiReturn == ERROR_INVALID_PARAMETER,
643        "GetIpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
644 
645     apiReturn = pGetIpStatisticsEx(&stats, AF_INET);
646     ok(apiReturn == NO_ERROR, "GetIpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
647     if (apiReturn == NO_ERROR && winetest_debug > 1)
648     {
649         trace( "IP IPv4 Ex stats:\n" );
650         trace( "    dwForwarding:      %u\n", U(stats).dwForwarding );
651         trace( "    dwDefaultTTL:      %u\n", stats.dwDefaultTTL );
652         trace( "    dwInReceives:      %u\n", stats.dwInReceives );
653         trace( "    dwInHdrErrors:     %u\n", stats.dwInHdrErrors );
654         trace( "    dwInAddrErrors:    %u\n", stats.dwInAddrErrors );
655         trace( "    dwForwDatagrams:   %u\n", stats.dwForwDatagrams );
656         trace( "    dwInUnknownProtos: %u\n", stats.dwInUnknownProtos );
657         trace( "    dwInDiscards:      %u\n", stats.dwInDiscards );
658         trace( "    dwInDelivers:      %u\n", stats.dwInDelivers );
659         trace( "    dwOutRequests:     %u\n", stats.dwOutRequests );
660         trace( "    dwRoutingDiscards: %u\n", stats.dwRoutingDiscards );
661         trace( "    dwOutDiscards:     %u\n", stats.dwOutDiscards );
662         trace( "    dwOutNoRoutes:     %u\n", stats.dwOutNoRoutes );
663         trace( "    dwReasmTimeout:    %u\n", stats.dwReasmTimeout );
664         trace( "    dwReasmReqds:      %u\n", stats.dwReasmReqds );
665         trace( "    dwReasmOks:        %u\n", stats.dwReasmOks );
666         trace( "    dwReasmFails:      %u\n", stats.dwReasmFails );
667         trace( "    dwFragOks:         %u\n", stats.dwFragOks );
668         trace( "    dwFragFails:       %u\n", stats.dwFragFails );
669         trace( "    dwFragCreates:     %u\n", stats.dwFragCreates );
670         trace( "    dwNumIf:           %u\n", stats.dwNumIf );
671         trace( "    dwNumAddr:         %u\n", stats.dwNumAddr );
672         trace( "    dwNumRoutes:       %u\n", stats.dwNumRoutes );
673     }
674 
675     apiReturn = pGetIpStatisticsEx(&stats, AF_INET6);
676     ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
677        "GetIpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
678     if (apiReturn == NO_ERROR && winetest_debug > 1)
679     {
680         trace( "IP IPv6 Ex stats:\n" );
681         trace( "    dwForwarding:      %u\n", U(stats).dwForwarding );
682         trace( "    dwDefaultTTL:      %u\n", stats.dwDefaultTTL );
683         trace( "    dwInReceives:      %u\n", stats.dwInReceives );
684         trace( "    dwInHdrErrors:     %u\n", stats.dwInHdrErrors );
685         trace( "    dwInAddrErrors:    %u\n", stats.dwInAddrErrors );
686         trace( "    dwForwDatagrams:   %u\n", stats.dwForwDatagrams );
687         trace( "    dwInUnknownProtos: %u\n", stats.dwInUnknownProtos );
688         trace( "    dwInDiscards:      %u\n", stats.dwInDiscards );
689         trace( "    dwInDelivers:      %u\n", stats.dwInDelivers );
690         trace( "    dwOutRequests:     %u\n", stats.dwOutRequests );
691         trace( "    dwRoutingDiscards: %u\n", stats.dwRoutingDiscards );
692         trace( "    dwOutDiscards:     %u\n", stats.dwOutDiscards );
693         trace( "    dwOutNoRoutes:     %u\n", stats.dwOutNoRoutes );
694         trace( "    dwReasmTimeout:    %u\n", stats.dwReasmTimeout );
695         trace( "    dwReasmReqds:      %u\n", stats.dwReasmReqds );
696         trace( "    dwReasmOks:        %u\n", stats.dwReasmOks );
697         trace( "    dwReasmFails:      %u\n", stats.dwReasmFails );
698         trace( "    dwFragOks:         %u\n", stats.dwFragOks );
699         trace( "    dwFragFails:       %u\n", stats.dwFragFails );
700         trace( "    dwFragCreates:     %u\n", stats.dwFragCreates );
701         trace( "    dwNumIf:           %u\n", stats.dwNumIf );
702         trace( "    dwNumAddr:         %u\n", stats.dwNumAddr );
703         trace( "    dwNumRoutes:       %u\n", stats.dwNumRoutes );
704     }
705 }
706 
testGetTcpStatisticsEx(void)707 static void testGetTcpStatisticsEx(void)
708 {
709     DWORD apiReturn;
710     MIB_TCPSTATS stats;
711 
712     if (!pGetTcpStatisticsEx)
713     {
714         win_skip( "GetTcpStatisticsEx not available\n" );
715         return;
716     }
717 
718     apiReturn = pGetTcpStatisticsEx(NULL, AF_INET);
719     ok(apiReturn == ERROR_INVALID_PARAMETER,
720        "GetTcpStatisticsEx(NULL, AF_INET); returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
721 
722     apiReturn = pGetTcpStatisticsEx(&stats, AF_BAN);
723     ok(apiReturn == ERROR_INVALID_PARAMETER || apiReturn == ERROR_NOT_SUPPORTED,
724        "GetTcpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
725 
726     apiReturn = pGetTcpStatisticsEx(&stats, AF_INET);
727     ok(apiReturn == NO_ERROR, "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
728     if (apiReturn == NO_ERROR && winetest_debug > 1)
729     {
730         trace( "TCP IPv4 Ex stats:\n" );
731         trace( "    dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
732         trace( "    dwRtoMin:       %u\n", stats.dwRtoMin );
733         trace( "    dwRtoMax:       %u\n", stats.dwRtoMax );
734         trace( "    dwMaxConn:      %u\n", stats.dwMaxConn );
735         trace( "    dwActiveOpens:  %u\n", stats.dwActiveOpens );
736         trace( "    dwPassiveOpens: %u\n", stats.dwPassiveOpens );
737         trace( "    dwAttemptFails: %u\n", stats.dwAttemptFails );
738         trace( "    dwEstabResets:  %u\n", stats.dwEstabResets );
739         trace( "    dwCurrEstab:    %u\n", stats.dwCurrEstab );
740         trace( "    dwInSegs:       %u\n", stats.dwInSegs );
741         trace( "    dwOutSegs:      %u\n", stats.dwOutSegs );
742         trace( "    dwRetransSegs:  %u\n", stats.dwRetransSegs );
743         trace( "    dwInErrs:       %u\n", stats.dwInErrs );
744         trace( "    dwOutRsts:      %u\n", stats.dwOutRsts );
745         trace( "    dwNumConns:     %u\n", stats.dwNumConns );
746     }
747 
748     apiReturn = pGetTcpStatisticsEx(&stats, AF_INET6);
749     todo_wine ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
750                  "GetTcpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
751     if (apiReturn == NO_ERROR && winetest_debug > 1)
752     {
753         trace( "TCP IPv6 Ex stats:\n" );
754         trace( "    dwRtoAlgorithm: %u\n", U(stats).dwRtoAlgorithm );
755         trace( "    dwRtoMin:       %u\n", stats.dwRtoMin );
756         trace( "    dwRtoMax:       %u\n", stats.dwRtoMax );
757         trace( "    dwMaxConn:      %u\n", stats.dwMaxConn );
758         trace( "    dwActiveOpens:  %u\n", stats.dwActiveOpens );
759         trace( "    dwPassiveOpens: %u\n", stats.dwPassiveOpens );
760         trace( "    dwAttemptFails: %u\n", stats.dwAttemptFails );
761         trace( "    dwEstabResets:  %u\n", stats.dwEstabResets );
762         trace( "    dwCurrEstab:    %u\n", stats.dwCurrEstab );
763         trace( "    dwInSegs:       %u\n", stats.dwInSegs );
764         trace( "    dwOutSegs:      %u\n", stats.dwOutSegs );
765         trace( "    dwRetransSegs:  %u\n", stats.dwRetransSegs );
766         trace( "    dwInErrs:       %u\n", stats.dwInErrs );
767         trace( "    dwOutRsts:      %u\n", stats.dwOutRsts );
768         trace( "    dwNumConns:     %u\n", stats.dwNumConns );
769     }
770 }
771 
testGetUdpStatisticsEx(void)772 static void testGetUdpStatisticsEx(void)
773 {
774     DWORD apiReturn;
775     MIB_UDPSTATS stats;
776 
777     if (!pGetUdpStatisticsEx)
778     {
779         win_skip( "GetUdpStatisticsEx not available\n" );
780         return;
781     }
782 
783     apiReturn = pGetUdpStatisticsEx(NULL, AF_INET);
784     ok(apiReturn == ERROR_INVALID_PARAMETER,
785        "GetUdpStatisticsEx(NULL, AF_INET); returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
786 
787     apiReturn = pGetUdpStatisticsEx(&stats, AF_BAN);
788     ok(apiReturn == ERROR_INVALID_PARAMETER || apiReturn == ERROR_NOT_SUPPORTED,
789        "GetUdpStatisticsEx(&stats, AF_BAN) returned %d, expected ERROR_INVALID_PARAMETER\n", apiReturn);
790 
791     apiReturn = pGetUdpStatisticsEx(&stats, AF_INET);
792     ok(apiReturn == NO_ERROR, "GetUdpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
793     if (apiReturn == NO_ERROR && winetest_debug > 1)
794     {
795         trace( "UDP IPv4 Ex stats:\n" );
796         trace( "    dwInDatagrams:  %u\n", stats.dwInDatagrams );
797         trace( "    dwNoPorts:      %u\n", stats.dwNoPorts );
798         trace( "    dwInErrors:     %u\n", stats.dwInErrors );
799         trace( "    dwOutDatagrams: %u\n", stats.dwOutDatagrams );
800         trace( "    dwNumAddrs:     %u\n", stats.dwNumAddrs );
801     }
802 
803     apiReturn = pGetUdpStatisticsEx(&stats, AF_INET6);
804     ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
805        "GetUdpStatisticsEx returned %d, expected NO_ERROR\n", apiReturn);
806     if (apiReturn == NO_ERROR && winetest_debug > 1)
807     {
808         trace( "UDP IPv6 Ex stats:\n" );
809         trace( "    dwInDatagrams:  %u\n", stats.dwInDatagrams );
810         trace( "    dwNoPorts:      %u\n", stats.dwNoPorts );
811         trace( "    dwInErrors:     %u\n", stats.dwInErrors );
812         trace( "    dwOutDatagrams: %u\n", stats.dwOutDatagrams );
813         trace( "    dwNumAddrs:     %u\n", stats.dwNumAddrs );
814     }
815 }
816 
testGetTcpTable(void)817 static void testGetTcpTable(void)
818 {
819   if (pGetTcpTable) {
820     DWORD apiReturn;
821     ULONG dwSize = 0;
822 
823     apiReturn = pGetTcpTable(NULL, &dwSize, FALSE);
824     if (apiReturn == ERROR_NOT_SUPPORTED) {
825       skip("GetTcpTable is not supported\n");
826       return;
827     }
828     ok(apiReturn == ERROR_INSUFFICIENT_BUFFER ||
829        broken(apiReturn == ERROR_NO_DATA), /* win95 */
830      "GetTcpTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
831      apiReturn);
832     if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
833       PMIB_TCPTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
834 
835       apiReturn = pGetTcpTable(buf, &dwSize, FALSE);
836       ok(apiReturn == NO_ERROR,
837        "GetTcpTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
838        apiReturn);
839 
840       if (apiReturn == NO_ERROR && winetest_debug > 1)
841       {
842           DWORD i;
843           trace( "TCP table: %u entries\n", buf->dwNumEntries );
844           for (i = 0; i < buf->dwNumEntries; i++)
845           {
846               char buffer[40];
847               sprintf( buffer, "local %s:%u",
848                        ntoa(buf->table[i].dwLocalAddr), ntohs(buf->table[i].dwLocalPort) );
849               trace( "%u: %s remote %s:%u state %u\n",
850                      i, buffer, ntoa( buf->table[i].dwRemoteAddr ),
851                      ntohs(buf->table[i].dwRemotePort), U(buf->table[i]).dwState );
852           }
853       }
854       HeapFree(GetProcessHeap(), 0, buf);
855     }
856   }
857 }
858 
testGetUdpTable(void)859 static void testGetUdpTable(void)
860 {
861   if (pGetUdpTable) {
862     DWORD apiReturn;
863     ULONG dwSize = 0;
864 
865     apiReturn = pGetUdpTable(NULL, &dwSize, FALSE);
866     if (apiReturn == ERROR_NOT_SUPPORTED) {
867       skip("GetUdpTable is not supported\n");
868       return;
869     }
870     ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
871      "GetUdpTable(NULL, &dwSize, FALSE) returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
872      apiReturn);
873     if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
874       PMIB_UDPTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
875 
876       apiReturn = pGetUdpTable(buf, &dwSize, FALSE);
877       ok(apiReturn == NO_ERROR,
878        "GetUdpTable(buf, &dwSize, FALSE) returned %d, expected NO_ERROR\n",
879        apiReturn);
880 
881       if (apiReturn == NO_ERROR && winetest_debug > 1)
882       {
883           DWORD i;
884           trace( "UDP table: %u entries\n", buf->dwNumEntries );
885           for (i = 0; i < buf->dwNumEntries; i++)
886               trace( "%u: %s:%u\n",
887                      i, ntoa( buf->table[i].dwLocalAddr ), ntohs(buf->table[i].dwLocalPort) );
888       }
889       HeapFree(GetProcessHeap(), 0, buf);
890     }
891   }
892 }
893 
testSetTcpEntry(void)894 static void testSetTcpEntry(void)
895 {
896     DWORD ret;
897     MIB_TCPROW row;
898 
899     memset(&row, 0, sizeof(row));
900     if(0) /* This test crashes in OS >= VISTA */
901     {
902         ret = pSetTcpEntry(NULL);
903         ok( ret == ERROR_INVALID_PARAMETER, "got %u, expected %u\n", ret, ERROR_INVALID_PARAMETER);
904     }
905 
906     ret = pSetTcpEntry(&row);
907     if (ret == ERROR_NETWORK_ACCESS_DENIED)
908     {
909         win_skip("SetTcpEntry failed with access error. Skipping test.\n");
910         return;
911     }
912     todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %u, expected %u\n", ret, ERROR_INVALID_PARAMETER);
913 
914     U(row).dwState = MIB_TCP_STATE_DELETE_TCB;
915     ret = pSetTcpEntry(&row);
916     todo_wine ok( ret == ERROR_MR_MID_NOT_FOUND || broken(ret == ERROR_INVALID_PARAMETER),
917        "got %u, expected %u\n", ret, ERROR_MR_MID_NOT_FOUND);
918 }
919 
testIcmpSendEcho(void)920 static void testIcmpSendEcho(void)
921 {
922     HANDLE icmp;
923     char senddata[32], replydata[sizeof(senddata) + sizeof(ICMP_ECHO_REPLY)];
924     DWORD ret, error, replysz = sizeof(replydata);
925     IPAddr address;
926 
927     if (!pIcmpSendEcho || !pIcmpCreateFile)
928     {
929         win_skip( "IcmpSendEcho or IcmpCreateFile not available\n" );
930         return;
931     }
932     memset(senddata, 0, sizeof(senddata));
933 
934     address = htonl(INADDR_LOOPBACK);
935     SetLastError(0xdeadbeef);
936     ret = pIcmpSendEcho(INVALID_HANDLE_VALUE, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
937     error = GetLastError();
938     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
939 todo_wine
940     ok (error == ERROR_INVALID_PARAMETER
941         || broken(error == ERROR_INVALID_HANDLE) /* <= 2003 */,
942         "expected 87, got %d\n", error);
943 
944     icmp = pIcmpCreateFile();
945     if (icmp == INVALID_HANDLE_VALUE)
946     {
947         error = GetLastError();
948         if (error == ERROR_ACCESS_DENIED)
949         {
950             skip ("ICMP is not available.\n");
951             return;
952         }
953     }
954     ok (icmp != INVALID_HANDLE_VALUE, "IcmpCreateFile failed unexpectedly with error %d\n", GetLastError());
955 
956     address = 0;
957     SetLastError(0xdeadbeef);
958     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
959     error = GetLastError();
960     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
961     ok (error == ERROR_INVALID_NETNAME
962         || broken(error == IP_BAD_DESTINATION) /* <= 2003 */,
963         "expected 1214, got %d\n", error);
964 
965     address = htonl(INADDR_LOOPBACK);
966     if (0) /* crashes in XP */
967     {
968         ret = pIcmpSendEcho(icmp, address, NULL, sizeof(senddata), NULL, replydata, replysz, 1000);
969         ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
970     }
971 
972     SetLastError(0xdeadbeef);
973     ret = pIcmpSendEcho(icmp, address, senddata, 0, NULL, replydata, replysz, 1000);
974     error = GetLastError();
975     ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
976 
977     SetLastError(0xdeadbeef);
978     ret = pIcmpSendEcho(icmp, address, NULL, 0, NULL, replydata, replysz, 1000);
979     error = GetLastError();
980     ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
981 
982     if (0) /* crashes in wine, remove IF when fixed */
983     {
984     SetLastError(0xdeadbeef);
985     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, NULL, replysz, 1000);
986     error = GetLastError();
987     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
988     ok (error == ERROR_INVALID_PARAMETER, "expected 87, got %d\n", error);
989     }
990 
991     SetLastError(0xdeadbeef);
992     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, 0, 1000);
993     error = GetLastError();
994     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
995 todo_wine
996     ok (error == ERROR_INVALID_PARAMETER
997         || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
998         "expected 87, got %d\n", error);
999 
1000     SetLastError(0xdeadbeef);
1001     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, NULL, 0, 1000);
1002     error = GetLastError();
1003     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1004 todo_wine
1005     ok (error == ERROR_INVALID_PARAMETER
1006         || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1007         "expected 87, got %d\n", error);
1008 
1009     SetLastError(0xdeadbeef);
1010     replysz = sizeof(replydata) - 1;
1011     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1012     error = GetLastError();
1013     todo_wine {
1014     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1015     ok (error == IP_GENERAL_FAILURE
1016         || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1017         "expected 11050, got %d\n", error);
1018     }
1019 
1020     SetLastError(0xdeadbeef);
1021     replysz = sizeof(ICMP_ECHO_REPLY);
1022     ret = pIcmpSendEcho(icmp, address, senddata, 0, NULL, replydata, replysz, 1000);
1023     error = GetLastError();
1024 todo_wine
1025     ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
1026 
1027     SetLastError(0xdeadbeef);
1028     replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
1029     ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz, 1000);
1030     error = GetLastError();
1031     ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
1032 
1033     SetLastError(0xdeadbeef);
1034     replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
1035     ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN + 1, NULL, replydata, replysz, 1000);
1036     error = GetLastError();
1037 todo_wine
1038     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1039 todo_wine
1040     ok (error == IP_GENERAL_FAILURE
1041         || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1042         "expected 11050, got %d\n", error);
1043 
1044     SetLastError(0xdeadbeef);
1045     ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz - 1, 1000);
1046     error = GetLastError();
1047     ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1048 todo_wine
1049     ok (error == IP_GENERAL_FAILURE
1050         || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1051         "expected 11050, got %d\n", error);
1052 
1053     /* in windows >= vista the timeout can't be invalid */
1054     SetLastError(0xdeadbeef);
1055     replysz = sizeof(replydata);
1056     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 0);
1057     error = GetLastError();
1058     if (!ret) ok(error == ERROR_INVALID_PARAMETER, "expected 87, got %d\n", error);
1059 
1060     SetLastError(0xdeadbeef);
1061     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, -1);
1062     error = GetLastError();
1063     if (!ret) ok(error == ERROR_INVALID_PARAMETER, "expected 87, got %d\n", error);
1064 
1065     /* real ping test */
1066     SetLastError(0xdeadbeef);
1067     address = htonl(INADDR_LOOPBACK);
1068     ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1069     error = GetLastError();
1070     if (ret)
1071     {
1072         PICMP_ECHO_REPLY pong = (PICMP_ECHO_REPLY) replydata;
1073         trace ("send addr  : %s\n", ntoa(address));
1074         trace ("reply addr : %s\n", ntoa(pong->Address));
1075         trace ("reply size : %u\n", replysz);
1076         trace ("roundtrip  : %u ms\n", pong->RoundTripTime);
1077         trace ("status     : %u\n", pong->Status);
1078         trace ("recv size  : %u\n", pong->DataSize);
1079         trace ("ttl        : %u\n", pong->Options.Ttl);
1080         trace ("flags      : 0x%x\n", pong->Options.Flags);
1081     }
1082     else
1083     {
1084         skip ("Failed to ping with error %d, is lo interface down?.\n", error);
1085     }
1086 }
1087 
1088 /*
1089 still-to-be-tested NT4-onward functions:
1090 CreateIpForwardEntry
1091 DeleteIpForwardEntry
1092 CreateIpNetEntry
1093 DeleteIpNetEntry
1094 GetFriendlyIfIndex
1095 GetRTTAndHopCount
1096 SetIfEntry
1097 SetIpForwardEntry
1098 SetIpNetEntry
1099 SetIpStatistics
1100 SetIpTTL
1101 */
testWinNT4Functions(void)1102 static void testWinNT4Functions(void)
1103 {
1104   testGetNumberOfInterfaces();
1105   testGetIpAddrTable();
1106   testGetIfTable();
1107   testGetIpForwardTable();
1108   testGetIpNetTable();
1109   testGetIcmpStatistics();
1110   testGetIpStatistics();
1111   testGetTcpStatistics();
1112   testGetUdpStatistics();
1113   testGetIcmpStatisticsEx();
1114   testGetIpStatisticsEx();
1115   testGetTcpStatisticsEx();
1116   testGetUdpStatisticsEx();
1117   testGetTcpTable();
1118   testGetUdpTable();
1119   testSetTcpEntry();
1120   testIcmpSendEcho();
1121 }
1122 
testGetInterfaceInfo(void)1123 static void testGetInterfaceInfo(void)
1124 {
1125   if (pGetInterfaceInfo) {
1126     DWORD apiReturn;
1127     ULONG len = 0;
1128 
1129     apiReturn = pGetInterfaceInfo(NULL, NULL);
1130     if (apiReturn == ERROR_NOT_SUPPORTED) {
1131       skip("GetInterfaceInfo is not supported\n");
1132       return;
1133     }
1134     ok(apiReturn == ERROR_INVALID_PARAMETER,
1135      "GetInterfaceInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
1136      apiReturn);
1137     apiReturn = pGetInterfaceInfo(NULL, &len);
1138     ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
1139      "GetInterfaceInfo returned %d, expected ERROR_INSUFFICIENT_BUFFER\n",
1140      apiReturn);
1141     if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
1142       PIP_INTERFACE_INFO buf = HeapAlloc(GetProcessHeap(), 0, len);
1143 
1144       apiReturn = pGetInterfaceInfo(buf, &len);
1145       ok(apiReturn == NO_ERROR,
1146        "GetInterfaceInfo(buf, &dwSize) returned %d, expected NO_ERROR\n",
1147        apiReturn);
1148       HeapFree(GetProcessHeap(), 0, buf);
1149     }
1150   }
1151 }
1152 
testGetAdaptersInfo(void)1153 static void testGetAdaptersInfo(void)
1154 {
1155   if (pGetAdaptersInfo) {
1156     DWORD apiReturn;
1157     ULONG len = 0;
1158 
1159     apiReturn = pGetAdaptersInfo(NULL, NULL);
1160     if (apiReturn == ERROR_NOT_SUPPORTED) {
1161       skip("GetAdaptersInfo is not supported\n");
1162       return;
1163     }
1164     ok(apiReturn == ERROR_INVALID_PARAMETER,
1165      "GetAdaptersInfo returned %d, expected ERROR_INVALID_PARAMETER\n",
1166      apiReturn);
1167     apiReturn = pGetAdaptersInfo(NULL, &len);
1168     ok(apiReturn == ERROR_NO_DATA || apiReturn == ERROR_BUFFER_OVERFLOW,
1169      "GetAdaptersInfo returned %d, expected ERROR_NO_DATA or ERROR_BUFFER_OVERFLOW\n",
1170      apiReturn);
1171     if (apiReturn == ERROR_NO_DATA)
1172       ; /* no adapter's, that's okay */
1173     else if (apiReturn == ERROR_BUFFER_OVERFLOW) {
1174       PIP_ADAPTER_INFO ptr, buf = HeapAlloc(GetProcessHeap(), 0, len);
1175 
1176       apiReturn = pGetAdaptersInfo(buf, &len);
1177       ok(apiReturn == NO_ERROR,
1178        "GetAdaptersInfo(buf, &dwSize) returned %d, expected NO_ERROR\n",
1179        apiReturn);
1180       ptr = buf;
1181       while (ptr) {
1182         ok(ptr->IpAddressList.IpAddress.String[0], "A valid IP must be present\n");
1183         ok(ptr->IpAddressList.IpMask.String[0], "A valid mask must be present\n");
1184         trace("Adapter '%s', IP %s, Mask %s\n", ptr->AdapterName,
1185               ptr->IpAddressList.IpAddress.String, ptr->IpAddressList.IpMask.String);
1186         ptr = ptr->Next;
1187       }
1188       HeapFree(GetProcessHeap(), 0, buf);
1189     }
1190   }
1191 }
1192 
testGetNetworkParams(void)1193 static void testGetNetworkParams(void)
1194 {
1195   if (pGetNetworkParams) {
1196     DWORD apiReturn;
1197     ULONG len = 0;
1198 
1199     apiReturn = pGetNetworkParams(NULL, NULL);
1200     if (apiReturn == ERROR_NOT_SUPPORTED) {
1201       skip("GetNetworkParams is not supported\n");
1202       return;
1203     }
1204     ok(apiReturn == ERROR_INVALID_PARAMETER,
1205      "GetNetworkParams returned %d, expected ERROR_INVALID_PARAMETER\n",
1206      apiReturn);
1207     apiReturn = pGetNetworkParams(NULL, &len);
1208     ok(apiReturn == ERROR_BUFFER_OVERFLOW,
1209      "GetNetworkParams returned %d, expected ERROR_BUFFER_OVERFLOW\n",
1210      apiReturn);
1211     if (apiReturn == ERROR_BUFFER_OVERFLOW) {
1212       PFIXED_INFO buf = HeapAlloc(GetProcessHeap(), 0, len);
1213 
1214       apiReturn = pGetNetworkParams(buf, &len);
1215       ok(apiReturn == NO_ERROR,
1216        "GetNetworkParams(buf, &dwSize) returned %d, expected NO_ERROR\n",
1217        apiReturn);
1218       HeapFree(GetProcessHeap(), 0, buf);
1219     }
1220   }
1221 }
1222 
1223 /*
1224 still-to-be-tested 98-onward functions:
1225 GetBestInterface
1226 GetBestRoute
1227 IpReleaseAddress
1228 IpRenewAddress
1229 */
testWin98Functions(void * p)1230 static DWORD CALLBACK testWin98Functions(void *p)
1231 {
1232   testGetInterfaceInfo();
1233   testGetAdaptersInfo();
1234   testGetNetworkParams();
1235   return 0;
1236 }
1237 
testGetPerAdapterInfo(void)1238 static void testGetPerAdapterInfo(void)
1239 {
1240     DWORD ret, needed;
1241     void *buffer;
1242 
1243     if (!pGetPerAdapterInfo) return;
1244     ret = pGetPerAdapterInfo(1, NULL, NULL);
1245     if (ret == ERROR_NOT_SUPPORTED) {
1246       skip("GetPerAdapterInfo is not supported\n");
1247       return;
1248     }
1249     ok( ret == ERROR_INVALID_PARAMETER, "got %u instead of ERROR_INVALID_PARAMETER\n", ret );
1250     needed = 0xdeadbeef;
1251     ret = pGetPerAdapterInfo(1, NULL, &needed);
1252     if (ret == ERROR_NO_DATA) return;  /* no such adapter */
1253     ok( ret == ERROR_BUFFER_OVERFLOW, "got %u instead of ERROR_BUFFER_OVERFLOW\n", ret );
1254     ok( needed != 0xdeadbeef, "needed not set\n" );
1255     buffer = HeapAlloc( GetProcessHeap(), 0, needed );
1256     ret = pGetPerAdapterInfo(1, buffer, &needed);
1257     ok( ret == NO_ERROR, "got %u instead of NO_ERROR\n", ret );
1258     HeapFree( GetProcessHeap(), 0, buffer );
1259 }
1260 
testNotifyAddrChange(void)1261 static void testNotifyAddrChange(void)
1262 {
1263     DWORD ret, bytes;
1264     OVERLAPPED overlapped;
1265     HANDLE handle;
1266     BOOL success;
1267 
1268     if (!pNotifyAddrChange)
1269     {
1270         win_skip("NotifyAddrChange not present\n");
1271         return;
1272     }
1273     if (!pCancelIPChangeNotify)
1274     {
1275         win_skip("CancelIPChangeNotify not present\n");
1276         return;
1277     }
1278 
1279     handle = NULL;
1280     ZeroMemory(&overlapped, sizeof(overlapped));
1281     ret = pNotifyAddrChange(&handle, &overlapped);
1282     if (ret == ERROR_NOT_SUPPORTED)
1283     {
1284         win_skip("NotifyAddrChange is not supported\n");
1285         return;
1286     }
1287     ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %d, expected ERROR_IO_PENDING\n", ret);
1288     ret = GetLastError();
1289     todo_wine ok(ret == ERROR_IO_PENDING, "GetLastError returned %d, expected ERROR_IO_PENDING\n", ret);
1290     success = pCancelIPChangeNotify(&overlapped);
1291     todo_wine ok(success == TRUE, "CancelIPChangeNotify returned FALSE, expected TRUE\n");
1292 
1293     ZeroMemory(&overlapped, sizeof(overlapped));
1294     success = pCancelIPChangeNotify(&overlapped);
1295     ok(success == FALSE, "CancelIPChangeNotify returned TRUE, expected FALSE\n");
1296 
1297     handle = NULL;
1298     ZeroMemory(&overlapped, sizeof(overlapped));
1299     overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1300     ret = pNotifyAddrChange(&handle, &overlapped);
1301     ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %d, expected ERROR_IO_PENDING\n", ret);
1302     todo_wine ok(handle != INVALID_HANDLE_VALUE, "NotifyAddrChange returned invalid file handle\n");
1303     success = GetOverlappedResult(handle, &overlapped, &bytes, FALSE);
1304     ok(success == FALSE, "GetOverlappedResult returned TRUE, expected FALSE\n");
1305     ret = GetLastError();
1306     ok(ret == ERROR_IO_INCOMPLETE, "GetLastError returned %d, expected ERROR_IO_INCOMPLETE\n", ret);
1307     success = pCancelIPChangeNotify(&overlapped);
1308     todo_wine ok(success == TRUE, "CancelIPChangeNotify returned FALSE, expected TRUE\n");
1309 
1310     if (winetest_interactive)
1311     {
1312         handle = NULL;
1313         ZeroMemory(&overlapped, sizeof(overlapped));
1314         overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1315         trace("Testing asynchronous ipv4 address change notification. Please "
1316               "change the ipv4 address of one of your network interfaces\n");
1317         ret = pNotifyAddrChange(&handle, &overlapped);
1318         ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %d, expected NO_ERROR\n", ret);
1319         success = GetOverlappedResult(handle, &overlapped, &bytes, TRUE);
1320         ok(success == TRUE, "GetOverlappedResult returned FALSE, expected TRUE\n");
1321     }
1322 
1323     /* test synchronous functionality */
1324     if (winetest_interactive)
1325     {
1326         trace("Testing synchronous ipv4 address change notification. Please "
1327               "change the ipv4 address of one of your network interfaces\n");
1328         ret = pNotifyAddrChange(NULL, NULL);
1329         todo_wine ok(ret == NO_ERROR, "NotifyAddrChange returned %d, expected NO_ERROR\n", ret);
1330     }
1331 }
1332 
1333 /*
1334 still-to-be-tested 2K-onward functions:
1335 AddIPAddress
1336 CreateProxyArpEntry
1337 DeleteIPAddress
1338 DeleteProxyArpEntry
1339 EnableRouter
1340 FlushIpNetTable
1341 GetAdapterIndex
1342 NotifyRouteChange + CancelIPChangeNotify
1343 SendARP
1344 UnenableRouter
1345 */
testWin2KFunctions(void)1346 static void testWin2KFunctions(void)
1347 {
1348     testGetPerAdapterInfo();
1349     testNotifyAddrChange();
1350 }
1351 
test_GetAdaptersAddresses(void)1352 static void test_GetAdaptersAddresses(void)
1353 {
1354     ULONG ret, size, osize, i;
1355     IP_ADAPTER_ADDRESSES *aa, *ptr;
1356     IP_ADAPTER_UNICAST_ADDRESS *ua;
1357 
1358     if (!pGetAdaptersAddresses)
1359     {
1360         win_skip("GetAdaptersAddresses not present\n");
1361         return;
1362     }
1363 
1364     ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, NULL);
1365     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", ret);
1366 
1367     /* size should be ignored and overwritten if buffer is NULL */
1368     size = 0x7fffffff;
1369     ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
1370     ok(ret == ERROR_BUFFER_OVERFLOW, "expected ERROR_BUFFER_OVERFLOW, got %u\n", ret);
1371     if (ret != ERROR_BUFFER_OVERFLOW) return;
1372 
1373     ptr = HeapAlloc(GetProcessHeap(), 0, size);
1374     ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, ptr, &size);
1375     ok(!ret, "expected ERROR_SUCCESS got %u\n", ret);
1376     HeapFree(GetProcessHeap(), 0, ptr);
1377 
1378     /* higher size must not be changed to lower size */
1379     size *= 2;
1380     osize = size;
1381     ptr = HeapAlloc(GetProcessHeap(), 0, osize);
1382     ret = pGetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, ptr, &osize);
1383     ok(!ret, "expected ERROR_SUCCESS got %u\n", ret);
1384     ok(osize == size, "expected %d, got %d\n", size, osize);
1385 
1386     for (aa = ptr; !ret && aa; aa = aa->Next)
1387     {
1388         char temp[128];
1389         IP_ADAPTER_PREFIX *prefix;
1390 
1391         ok(S(U(*aa)).Length == sizeof(IP_ADAPTER_ADDRESSES_LH) ||
1392            S(U(*aa)).Length == sizeof(IP_ADAPTER_ADDRESSES_XP),
1393            "Unknown structure size of %u bytes\n", S(U(*aa)).Length);
1394         ok(aa->DnsSuffix != NULL, "DnsSuffix is not a valid pointer\n");
1395         ok(aa->Description != NULL, "Description is not a valid pointer\n");
1396         ok(aa->FriendlyName != NULL, "FriendlyName is not a valid pointer\n");
1397 
1398         trace("\n");
1399         trace("Length:                %u\n", S(U(*aa)).Length);
1400         trace("IfIndex:               %u\n", S(U(*aa)).IfIndex);
1401         trace("Next:                  %p\n", aa->Next);
1402         trace("AdapterName:           %s\n", aa->AdapterName);
1403         trace("FirstUnicastAddress:   %p\n", aa->FirstUnicastAddress);
1404         ua = aa->FirstUnicastAddress;
1405         while (ua)
1406         {
1407             ok(ua->PrefixOrigin != IpPrefixOriginOther,
1408                "bad address config value %d\n", ua->PrefixOrigin);
1409             ok(ua->SuffixOrigin != IpSuffixOriginOther,
1410                "bad address config value %d\n", ua->PrefixOrigin);
1411             /* Address configured manually or from DHCP server? */
1412             if (ua->PrefixOrigin == IpPrefixOriginManual ||
1413                 ua->PrefixOrigin == IpPrefixOriginDhcp)
1414             {
1415                 ok(ua->ValidLifetime, "expected non-zero value\n");
1416                 ok(ua->PreferredLifetime, "expected non-zero value\n");
1417                 ok(ua->LeaseLifetime, "expected non-zero\n");
1418             }
1419             /* Is the address ok in the network (not duplicated)? */
1420             ok(ua->DadState != IpDadStateInvalid && ua->DadState != IpDadStateDuplicate,
1421                "bad address duplication value %d\n", ua->DadState);
1422             trace("\tLength:                  %u\n", S(U(*ua)).Length);
1423             trace("\tFlags:                   0x%08x\n", S(U(*ua)).Flags);
1424             trace("\tNext:                    %p\n", ua->Next);
1425             trace("\tAddress.lpSockaddr:      %p\n", ua->Address.lpSockaddr);
1426             trace("\tAddress.iSockaddrLength: %d\n", ua->Address.iSockaddrLength);
1427             trace("\tPrefixOrigin:            %u\n", ua->PrefixOrigin);
1428             trace("\tSuffixOrigin:            %u\n", ua->SuffixOrigin);
1429             trace("\tDadState:                %u\n", ua->DadState);
1430             trace("\tValidLifetime:           %u seconds\n", ua->ValidLifetime);
1431             trace("\tPreferredLifetime:       %u seconds\n", ua->PreferredLifetime);
1432             trace("\tLeaseLifetime:           %u seconds\n", ua->LeaseLifetime);
1433             trace("\n");
1434             ua = ua->Next;
1435         }
1436         trace("FirstAnycastAddress:   %p\n", aa->FirstAnycastAddress);
1437         trace("FirstMulticastAddress: %p\n", aa->FirstMulticastAddress);
1438         trace("FirstDnsServerAddress: %p\n", aa->FirstDnsServerAddress);
1439         trace("DnsSuffix:             %s %p\n", wine_dbgstr_w(aa->DnsSuffix), aa->DnsSuffix);
1440         trace("Description:           %s %p\n", wine_dbgstr_w(aa->Description), aa->Description);
1441         trace("FriendlyName:          %s %p\n", wine_dbgstr_w(aa->FriendlyName), aa->FriendlyName);
1442         trace("PhysicalAddressLength: %u\n", aa->PhysicalAddressLength);
1443         for (i = 0; i < aa->PhysicalAddressLength; i++)
1444             sprintf(temp + i * 3, "%02X-", aa->PhysicalAddress[i]);
1445         temp[i ? i * 3 - 1 : 0] = '\0';
1446         trace("PhysicalAddress:       %s\n", temp);
1447         trace("Flags:                 0x%08x\n", aa->Flags);
1448         trace("Mtu:                   %u\n", aa->Mtu);
1449         trace("IfType:                %u\n", aa->IfType);
1450         trace("OperStatus:            %u\n", aa->OperStatus);
1451         trace("Ipv6IfIndex:           %u\n", aa->Ipv6IfIndex);
1452         for (i = 0, temp[0] = '\0'; i < sizeof(aa->ZoneIndices) / sizeof(aa->ZoneIndices[0]); i++)
1453             sprintf(temp + strlen(temp), "%d ", aa->ZoneIndices[i]);
1454         trace("ZoneIndices:           %s\n", temp);
1455         trace("FirstPrefix:           %p\n", aa->FirstPrefix);
1456         prefix = aa->FirstPrefix;
1457         while (prefix)
1458         {
1459             trace("\tLength:                  %u\n", S(U(*prefix)).Length);
1460             trace("\tFlags:                   0x%08x\n", S(U(*prefix)).Flags);
1461             trace("\tNext:                    %p\n", prefix->Next);
1462             trace("\tAddress.lpSockaddr:      %p\n", prefix->Address.lpSockaddr);
1463             trace("\tAddress.iSockaddrLength: %d\n", prefix->Address.iSockaddrLength);
1464             trace("\tPrefixLength:            %u\n", prefix->PrefixLength);
1465             trace("\n");
1466             prefix = prefix->Next;
1467         }
1468 
1469         if (S(U(*aa)).Length < sizeof(IP_ADAPTER_ADDRESSES_LH)) continue;
1470 #ifndef __REACTOS__
1471         trace("TransmitLinkSpeed:     %s\n", debugstr_longlong(aa->TransmitLinkSpeed));
1472         trace("ReceiveLinkSpeed:      %s\n", debugstr_longlong(aa->ReceiveLinkSpeed));
1473         trace("FirstWinsServerAddress:%p\n", aa->FirstWinsServerAddress);
1474         trace("FirstGatewayAddress:   %p\n", aa->FirstGatewayAddress);
1475         trace("Ipv4Metric:            %u\n", aa->Ipv4Metric);
1476         trace("Ipv6Metric:            %u\n", aa->Ipv6Metric);
1477         trace("Luid:                  %p\n", &aa->Luid);
1478         trace("Dhcpv4Server:          %p\n", &aa->Dhcpv4Server);
1479         trace("CompartmentId:         %u\n", aa->CompartmentId);
1480         trace("NetworkGuid:           %s\n", wine_dbgstr_guid((GUID*) &aa->NetworkGuid));
1481         trace("ConnectionType:        %u\n", aa->ConnectionType);
1482         trace("TunnelType:            %u\n", aa->TunnelType);
1483         trace("Dhcpv6Server:          %p\n", &aa->Dhcpv6Server);
1484         trace("Dhcpv6ClientDuidLength:%u\n", aa->Dhcpv6ClientDuidLength);
1485         trace("Dhcpv6ClientDuid:      %p\n", aa->Dhcpv6ClientDuid);
1486         trace("Dhcpv6Iaid:            %u\n", aa->Dhcpv6Iaid);
1487         trace("FirstDnsSuffix:        %p\n", aa->FirstDnsSuffix);
1488         trace("\n");
1489 #endif
1490     }
1491     HeapFree(GetProcessHeap(), 0, ptr);
1492 }
1493 
test_GetExtendedTcpTable(void)1494 static void test_GetExtendedTcpTable(void)
1495 {
1496     DWORD ret, size;
1497     MIB_TCPTABLE *table;
1498     MIB_TCPTABLE_OWNER_PID *table_pid;
1499     MIB_TCPTABLE_OWNER_MODULE *table_module;
1500 
1501     if (!pGetExtendedTcpTable)
1502     {
1503         win_skip("GetExtendedTcpTable not available\n");
1504         return;
1505     }
1506     ret = pGetExtendedTcpTable( NULL, NULL, TRUE, AF_INET, TCP_TABLE_BASIC_ALL, 0 );
1507     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1508 
1509     size = 0;
1510     ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_BASIC_ALL, 0 );
1511     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1512 
1513     table = HeapAlloc( GetProcessHeap(), 0, size );
1514     ret = pGetExtendedTcpTable( table, &size, TRUE, AF_INET, TCP_TABLE_BASIC_ALL, 0 );
1515     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1516     HeapFree( GetProcessHeap(), 0, table );
1517 
1518     size = 0;
1519     ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_BASIC_LISTENER, 0 );
1520     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1521 
1522     table = HeapAlloc( GetProcessHeap(), 0, size );
1523     ret = pGetExtendedTcpTable( table, &size, TRUE, AF_INET, TCP_TABLE_BASIC_LISTENER, 0 );
1524     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1525     HeapFree( GetProcessHeap(), 0, table );
1526 
1527     size = 0;
1528     ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0 );
1529     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1530 
1531     table_pid = HeapAlloc( GetProcessHeap(), 0, size );
1532     ret = pGetExtendedTcpTable( table_pid, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0 );
1533     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1534     HeapFree( GetProcessHeap(), 0, table_pid );
1535 
1536     size = 0;
1537     ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0 );
1538     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1539 
1540     table_pid = HeapAlloc( GetProcessHeap(), 0, size );
1541     ret = pGetExtendedTcpTable( table_pid, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0 );
1542     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1543     HeapFree( GetProcessHeap(), 0, table_pid );
1544 
1545     size = 0;
1546     ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0 );
1547     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1548 
1549     table_module = HeapAlloc( GetProcessHeap(), 0, size );
1550     ret = pGetExtendedTcpTable( table_module, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0 );
1551     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1552     HeapFree( GetProcessHeap(), 0, table_module );
1553 
1554     size = 0;
1555     ret = pGetExtendedTcpTable( NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_LISTENER, 0 );
1556     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1557 
1558     table_module = HeapAlloc( GetProcessHeap(), 0, size );
1559     ret = pGetExtendedTcpTable( table_module, &size, TRUE, AF_INET, TCP_TABLE_OWNER_MODULE_LISTENER, 0 );
1560     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1561     HeapFree( GetProcessHeap(), 0, table_module );
1562 }
1563 
test_GetExtendedUdpTable(void)1564 static void test_GetExtendedUdpTable(void)
1565 {
1566     DWORD ret, size;
1567     MIB_UDPTABLE *table;
1568     MIB_UDPTABLE_OWNER_PID *table_pid;
1569     MIB_UDPTABLE_OWNER_MODULE *table_module;
1570 
1571     if (!pGetExtendedUdpTable)
1572     {
1573         win_skip("GetExtendedUdpTable not available\n");
1574         return;
1575     }
1576     ret = pGetExtendedUdpTable( NULL, NULL, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
1577     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1578 
1579     size = 0;
1580     ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
1581     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1582 
1583     table = HeapAlloc( GetProcessHeap(), 0, size );
1584     ret = pGetExtendedUdpTable( table, &size, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
1585     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1586     HeapFree( GetProcessHeap(), 0, table );
1587 
1588     size = 0;
1589     ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0 );
1590     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1591 
1592     table_pid = HeapAlloc( GetProcessHeap(), 0, size );
1593     ret = pGetExtendedUdpTable( table_pid, &size, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0 );
1594     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1595     HeapFree( GetProcessHeap(), 0, table_pid );
1596 
1597     size = 0;
1598     ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_OWNER_MODULE, 0 );
1599     ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
1600 
1601     table_module = HeapAlloc( GetProcessHeap(), 0, size );
1602     ret = pGetExtendedUdpTable( table_module, &size, TRUE, AF_INET, UDP_TABLE_OWNER_MODULE, 0 );
1603     ok( ret == ERROR_SUCCESS, "got %u\n", ret );
1604     HeapFree( GetProcessHeap(), 0, table_module );
1605 }
1606 
test_CreateSortedAddressPairs(void)1607 static void test_CreateSortedAddressPairs(void)
1608 {
1609     SOCKADDR_IN6 dst[2];
1610     SOCKADDR_IN6_PAIR *pair;
1611     ULONG pair_count;
1612     DWORD ret;
1613 
1614     if (!pCreateSortedAddressPairs)
1615     {
1616         win_skip( "CreateSortedAddressPairs not available\n" );
1617         return;
1618     }
1619 
1620     memset( dst, 0, sizeof(dst) );
1621     dst[0].sin6_family = AF_INET6;
1622     dst[0].sin6_addr.u.Word[5] = 0xffff;
1623     dst[0].sin6_addr.u.Word[6] = 0x0808;
1624     dst[0].sin6_addr.u.Word[7] = 0x0808;
1625 
1626     pair_count = 0xdeadbeef;
1627     ret = pCreateSortedAddressPairs( NULL, 0, dst, 1, 0, NULL, &pair_count );
1628     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1629     ok( pair_count == 0xdeadbeef, "got %u\n", pair_count );
1630 
1631     pair = (SOCKADDR_IN6_PAIR *)0xdeadbeef;
1632     pair_count = 0xdeadbeef;
1633     ret = pCreateSortedAddressPairs( NULL, 0, NULL, 1, 0, &pair, &pair_count );
1634     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1635     ok( pair == (SOCKADDR_IN6_PAIR *)0xdeadbeef, "got %p\n", pair );
1636     ok( pair_count == 0xdeadbeef, "got %u\n", pair_count );
1637 
1638     pair = NULL;
1639     pair_count = 0xdeadbeef;
1640     ret = pCreateSortedAddressPairs( NULL, 0, dst, 1, 0, &pair, &pair_count );
1641     ok( ret == NO_ERROR, "got %u\n", ret );
1642     ok( pair != NULL, "pair not set\n" );
1643     ok( pair_count >= 1, "got %u\n", pair_count );
1644     ok( pair[0].SourceAddress != NULL, "src address not set\n" );
1645     ok( pair[0].DestinationAddress != NULL, "dst address not set\n" );
1646     pFreeMibTable( pair );
1647 
1648     dst[1].sin6_family = AF_INET6;
1649     dst[1].sin6_addr.u.Word[5] = 0xffff;
1650     dst[1].sin6_addr.u.Word[6] = 0x0404;
1651     dst[1].sin6_addr.u.Word[7] = 0x0808;
1652 
1653     pair = NULL;
1654     pair_count = 0xdeadbeef;
1655     ret = pCreateSortedAddressPairs( NULL, 0, dst, 2, 0, &pair, &pair_count );
1656     ok( ret == NO_ERROR, "got %u\n", ret );
1657     ok( pair != NULL, "pair not set\n" );
1658     ok( pair_count >= 2, "got %u\n", pair_count );
1659     ok( pair[0].SourceAddress != NULL, "src address not set\n" );
1660     ok( pair[0].DestinationAddress != NULL, "dst address not set\n" );
1661     ok( pair[1].SourceAddress != NULL, "src address not set\n" );
1662     ok( pair[1].DestinationAddress != NULL, "dst address not set\n" );
1663     pFreeMibTable( pair );
1664 }
1665 
get_interface_index(void)1666 static DWORD get_interface_index(void)
1667 {
1668     DWORD size = 0, ret = 0;
1669     IP_ADAPTER_ADDRESSES *buf, *aa;
1670 
1671     if (pGetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size ) != ERROR_BUFFER_OVERFLOW)
1672         return 0;
1673 
1674     buf = HeapAlloc( GetProcessHeap(), 0, size );
1675     pGetAdaptersAddresses( AF_UNSPEC, 0, NULL, buf, &size );
1676     for (aa = buf; aa; aa = aa->Next)
1677     {
1678         if (aa->IfType == IF_TYPE_ETHERNET_CSMACD)
1679         {
1680             ret = aa->IfIndex;
1681             break;
1682         }
1683     }
1684     HeapFree( GetProcessHeap(), 0, buf );
1685     return ret;
1686 }
1687 
test_interface_identifier_conversion(void)1688 static void test_interface_identifier_conversion(void)
1689 {
1690     DWORD ret;
1691     NET_LUID luid;
1692     GUID guid;
1693     SIZE_T len;
1694     WCHAR nameW[IF_MAX_STRING_SIZE + 1];
1695     char nameA[IF_MAX_STRING_SIZE + 1];
1696     NET_IFINDEX index;
1697 
1698     if (!pConvertInterfaceIndexToLuid)
1699     {
1700         win_skip( "ConvertInterfaceIndexToLuid not available\n" );
1701         return;
1702     }
1703     if (!(index = get_interface_index()))
1704     {
1705         skip( "no suitable interface found\n" );
1706         return;
1707     }
1708 
1709     /* ConvertInterfaceIndexToLuid */
1710     ret = pConvertInterfaceIndexToLuid( 0, NULL );
1711     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1712 
1713     memset( &luid, 0xff, sizeof(luid) );
1714     ret = pConvertInterfaceIndexToLuid( 0, &luid );
1715     ok( ret == ERROR_FILE_NOT_FOUND, "got %u\n", ret );
1716     ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1717     ok( !luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex );
1718     ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType );
1719 
1720     luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1721     ret = pConvertInterfaceIndexToLuid( index, &luid );
1722     ok( !ret, "got %u\n", ret );
1723     ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1724     ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1725     ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1726 
1727     /* ConvertInterfaceLuidToIndex */
1728     ret = pConvertInterfaceLuidToIndex( NULL, NULL );
1729     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1730 
1731     ret = pConvertInterfaceLuidToIndex( NULL, &index );
1732     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1733 
1734     ret = pConvertInterfaceLuidToIndex( &luid, NULL );
1735     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1736 
1737     ret = pConvertInterfaceLuidToIndex( &luid, &index );
1738     ok( !ret, "got %u\n", ret );
1739 
1740     /* ConvertInterfaceLuidToGuid */
1741     ret = pConvertInterfaceLuidToGuid( NULL, NULL );
1742     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1743 
1744     memset( &guid, 0xff, sizeof(guid) );
1745     ret = pConvertInterfaceLuidToGuid( NULL, &guid );
1746     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1747     ok( guid.Data1 == 0xffffffff, "got %x\n", guid.Data1 );
1748 
1749     ret = pConvertInterfaceLuidToGuid( &luid, NULL );
1750     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1751 
1752     memset( &guid, 0, sizeof(guid) );
1753     ret = pConvertInterfaceLuidToGuid( &luid, &guid );
1754     ok( !ret, "got %u\n", ret );
1755     ok( guid.Data1, "got %x\n", guid.Data1 );
1756 
1757     /* ConvertInterfaceGuidToLuid */
1758     ret = pConvertInterfaceGuidToLuid( NULL, NULL );
1759     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1760 
1761     luid.Info.NetLuidIndex = 1;
1762     ret = pConvertInterfaceGuidToLuid( NULL, &luid );
1763     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1764     ok( luid.Info.NetLuidIndex == 1, "got %u\n", luid.Info.NetLuidIndex );
1765 
1766     ret = pConvertInterfaceGuidToLuid( &guid, NULL );
1767     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1768 
1769     luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1770     ret = pConvertInterfaceGuidToLuid( &guid, &luid );
1771     ok( !ret, "got %u\n", ret );
1772     ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1773     ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1774     ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1775 
1776     /* ConvertInterfaceLuidToNameW */
1777     ret = pConvertInterfaceLuidToNameW( NULL, NULL, 0 );
1778     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1779 
1780     ret = pConvertInterfaceLuidToNameW( &luid, NULL, 0 );
1781     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1782 
1783     ret = pConvertInterfaceLuidToNameW( NULL, nameW, 0 );
1784     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1785 
1786     ret = pConvertInterfaceLuidToNameW( &luid, nameW, 0 );
1787     ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret );
1788 
1789     nameW[0] = 0;
1790     len = sizeof(nameW)/sizeof(nameW[0]);
1791     ret = pConvertInterfaceLuidToNameW( &luid, nameW, len );
1792     ok( !ret, "got %u\n", ret );
1793     ok( nameW[0], "name not set\n" );
1794 
1795     /* ConvertInterfaceLuidToNameA */
1796     ret = pConvertInterfaceLuidToNameA( NULL, NULL, 0 );
1797     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1798 
1799     ret = pConvertInterfaceLuidToNameA( &luid, NULL, 0 );
1800     ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret );
1801 
1802     ret = pConvertInterfaceLuidToNameA( NULL, nameA, 0 );
1803     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1804 
1805     ret = pConvertInterfaceLuidToNameA( &luid, nameA, 0 );
1806     ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %u\n", ret );
1807 
1808     nameA[0] = 0;
1809     len = sizeof(nameA)/sizeof(nameA[0]);
1810     ret = pConvertInterfaceLuidToNameA( &luid, nameA, len );
1811     ok( !ret, "got %u\n", ret );
1812     ok( nameA[0], "name not set\n" );
1813 
1814     /* ConvertInterfaceNameToLuidW */
1815     ret = pConvertInterfaceNameToLuidW( NULL, NULL );
1816     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1817 
1818     luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1819     ret = pConvertInterfaceNameToLuidW( NULL, &luid );
1820     ok( ret == ERROR_INVALID_NAME, "got %u\n", ret );
1821     ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1822     ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1823     ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType );
1824 
1825     ret = pConvertInterfaceNameToLuidW( nameW, NULL );
1826     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1827 
1828     luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1829     ret = pConvertInterfaceNameToLuidW( nameW, &luid );
1830     ok( !ret, "got %u\n", ret );
1831     ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1832     ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1833     ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1834 
1835     /* ConvertInterfaceNameToLuidA */
1836     ret = pConvertInterfaceNameToLuidA( NULL, NULL );
1837     ok( ret == ERROR_INVALID_NAME, "got %u\n", ret );
1838 
1839     luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1840     ret = pConvertInterfaceNameToLuidA( NULL, &luid );
1841     ok( ret == ERROR_INVALID_NAME, "got %u\n", ret );
1842     ok( luid.Info.Reserved == 0xdead, "reserved set\n" );
1843     ok( luid.Info.NetLuidIndex == 0xdead, "index set\n" );
1844     ok( luid.Info.IfType == 0xdead, "type set\n" );
1845 
1846     ret = pConvertInterfaceNameToLuidA( nameA, NULL );
1847     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1848 
1849     luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
1850     ret = pConvertInterfaceNameToLuidA( nameA, &luid );
1851     ok( !ret, "got %u\n", ret );
1852     ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
1853     ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
1854     ok( luid.Info.IfType == IF_TYPE_ETHERNET_CSMACD, "got %u\n", luid.Info.IfType );
1855 }
1856 
test_GetIfEntry2(void)1857 static void test_GetIfEntry2(void)
1858 {
1859     DWORD ret;
1860     MIB_IF_ROW2 row;
1861     NET_IFINDEX index;
1862 
1863     if (!pGetIfEntry2)
1864     {
1865         win_skip( "GetIfEntry2 not available\n" );
1866         return;
1867     }
1868     if (!(index = get_interface_index()))
1869     {
1870         skip( "no suitable interface found\n" );
1871         return;
1872     }
1873 
1874     ret = pGetIfEntry2( NULL );
1875     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1876 
1877     memset( &row, 0, sizeof(row) );
1878     ret = pGetIfEntry2( &row );
1879     ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
1880 
1881     memset( &row, 0, sizeof(row) );
1882     row.InterfaceIndex = index;
1883     ret = pGetIfEntry2( &row );
1884     ok( ret == NO_ERROR, "got %u\n", ret );
1885     ok( row.InterfaceIndex == index, "got %u\n", index );
1886 }
1887 
test_GetIfTable2(void)1888 static void test_GetIfTable2(void)
1889 {
1890     DWORD ret;
1891     MIB_IF_TABLE2 *table;
1892 
1893     if (!pGetIfTable2)
1894     {
1895         win_skip( "GetIfTable2 not available\n" );
1896         return;
1897     }
1898 
1899     table = NULL;
1900     ret = pGetIfTable2( &table );
1901     ok( ret == NO_ERROR, "got %u\n", ret );
1902     ok( table != NULL, "table not set\n" );
1903     pFreeMibTable( table );
1904 }
1905 
START_TEST(iphlpapi)1906 START_TEST(iphlpapi)
1907 {
1908 
1909   loadIPHlpApi();
1910   if (hLibrary) {
1911     HANDLE thread;
1912 
1913     testWin98OnlyFunctions();
1914     testWinNT4Functions();
1915 
1916     /* run testGetXXXX in two threads at once to make sure we don't crash in that case */
1917     thread = CreateThread(NULL, 0, testWin98Functions, NULL, 0, NULL);
1918     testWin98Functions(NULL);
1919     WaitForSingleObject(thread, INFINITE);
1920 
1921     testWin2KFunctions();
1922     test_GetAdaptersAddresses();
1923     test_GetExtendedTcpTable();
1924     test_GetExtendedUdpTable();
1925     test_CreateSortedAddressPairs();
1926     test_interface_identifier_conversion();
1927     test_GetIfEntry2();
1928     test_GetIfTable2();
1929     freeIPHlpApi();
1930   }
1931 }
1932