Reactos
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 ANSI 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 "winternl.h"
42#include "ws2tcpip.h"
43#include "windns.h"
44#include "iphlpapi.h"
45#include "icmpapi.h"
46#include "iprtrmib.h"
47#include "netioapi.h"
48#include "wine/test.h"
49#include <stdio.h>
50#include <stdlib.h>
51#ifdef __REACTOS__
52#include <versionhelpers.h>
53const IN6_ADDR in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }};
54#endif
55
56#define ICMP_MINLEN 8 /* copied from dlls/iphlpapi/ip_icmp.h file */
57
58static HMODULE hLibrary = NULL;
59
60static DWORD (WINAPI *pAllocateAndGetTcpExTableFromStack)(void**,BOOL,HANDLE,DWORD,DWORD);
61static DWORD (WINAPI *pGetTcp6Table)(PMIB_TCP6TABLE,PDWORD,BOOL);
62static DWORD (WINAPI *pGetUdp6Table)(PMIB_UDP6TABLE,PDWORD,BOOL);
63static DWORD (WINAPI *pGetUnicastIpAddressEntry)(MIB_UNICASTIPADDRESS_ROW*);
64static DWORD (WINAPI *pGetUnicastIpAddressTable)(ADDRESS_FAMILY,MIB_UNICASTIPADDRESS_TABLE**);
65static DWORD (WINAPI *pGetExtendedTcpTable)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG);
66static DWORD (WINAPI *pGetExtendedUdpTable)(PVOID,PDWORD,BOOL,ULONG,UDP_TABLE_CLASS,ULONG);
67static DWORD (WINAPI *pCreateSortedAddressPairs)(const PSOCKADDR_IN6,ULONG,const PSOCKADDR_IN6,ULONG,ULONG,
68 PSOCKADDR_IN6_PAIR*,ULONG*);
69static DWORD (WINAPI *pConvertLengthToIpv4Mask)(ULONG,ULONG*);
70static DWORD (WINAPI *pParseNetworkString)(const WCHAR*,DWORD,NET_ADDRESS_INFO*,USHORT*,BYTE*);
71static DWORD (WINAPI *pNotifyUnicastIpAddressChange)(ADDRESS_FAMILY, PUNICAST_IPADDRESS_CHANGE_CALLBACK,
72 PVOID, BOOLEAN, HANDLE *);
73static DWORD (WINAPI *pCancelMibChangeNotify2)(HANDLE);
74
75#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
76static DWORD (WINAPI *pConvertInterfaceAliasToLuid)(const WCHAR*,NET_LUID*);
77static DWORD (WINAPI *pConvertInterfaceLuidToAlias)(NET_LUID*,WCHAR*,SIZE_T);
78static DWORD (WINAPI *pConvertGuidToStringA)(const GUID*,char*,DWORD);
79static DWORD (WINAPI *pConvertGuidToStringW)(const GUID*,WCHAR*,DWORD);
80static DWORD (WINAPI *pConvertStringToGuidW)(const WCHAR*,GUID*);
81static DWORD (WINAPI *pGetIfEntry2)(PMIB_IF_ROW2);
82static DWORD (WINAPI *pGetIfTable2)(PMIB_IF_TABLE2*);
83static DWORD (WINAPI *pGetIfTable2Ex)(MIB_IF_TABLE_LEVEL,MIB_IF_TABLE2**);
84static DWORD (WINAPI *pGetIpForwardTable2)(ADDRESS_FAMILY,MIB_IPFORWARD_TABLE2**);
85static DWORD (WINAPI *pGetIpNetTable2)(ADDRESS_FAMILY,MIB_IPNET_TABLE2**);
86static void (WINAPI *pFreeMibTable)(void*);
87static DWORD (WINAPI *pConvertInterfaceGuidToLuid)(const GUID*,NET_LUID*);
88static DWORD (WINAPI *pConvertInterfaceIndexToLuid)(NET_IFINDEX,NET_LUID*);
89static DWORD (WINAPI *pConvertInterfaceLuidToGuid)(const NET_LUID*,GUID*);
90static DWORD (WINAPI *pConvertInterfaceLuidToIndex)(const NET_LUID*,NET_IFINDEX*);
91static DWORD (WINAPI *pConvertInterfaceLuidToNameA)(const NET_LUID*,char*,SIZE_T);
92static DWORD (WINAPI *pConvertInterfaceLuidToNameW)(const NET_LUID*,WCHAR*,SIZE_T);
93static DWORD (WINAPI *pConvertInterfaceNameToLuidA)(const char*,NET_LUID*);
94static DWORD (WINAPI *pConvertInterfaceNameToLuidW)(const WCHAR*,NET_LUID*);
95static NET_IF_COMPARTMENT_ID (WINAPI *pGetCurrentThreadCompartmentId)();
96static char* (WINAPI *pif_indextoname)(NET_IFINDEX,char*);
97static IF_INDEX (WINAPI *pif_nametoindex)(const char*);
98
99#define ConvertInterfaceAliasToLuid pConvertInterfaceAliasToLuid
100#define ConvertInterfaceLuidToAlias pConvertInterfaceLuidToAlias
101#define ConvertGuidToStringA pConvertGuidToStringA
102#define ConvertGuidToStringW pConvertGuidToStringW
103#define ConvertStringToGuidW pConvertStringToGuidW
104#define GetIfEntry2 pGetIfEntry2
105#define GetIfTable2 pGetIfTable2
106#define GetIfTable2Ex pGetIfTable2Ex
107#define GetIpForwardTable2 pGetIpForwardTable2
108#define GetIpNetTable2 pGetIpNetTable2
109#define FreeMibTable pFreeMibTable
110#define ConvertInterfaceGuidToLuid pConvertInterfaceGuidToLuid
111#define ConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid
112#define ConvertInterfaceLuidToGuid pConvertInterfaceLuidToGuid
113#define ConvertInterfaceLuidToIndex pConvertInterfaceLuidToIndex
114#define ConvertInterfaceLuidToNameA pConvertInterfaceLuidToNameA
115#define ConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW
116#define ConvertInterfaceNameToLuidA pConvertInterfaceNameToLuidA
117#define ConvertInterfaceNameToLuidW pConvertInterfaceNameToLuidW
118#define GetCurrentThreadCompartmentId pGetCurrentThreadCompartmentId
119#define if_indextoname pif_indextoname
120#define if_nametoindex pif_nametoindex
121
122/* Wine mistakes */
123#define GetUnicastIpAddressTable pGetUnicastIpAddressTable
124#define ConvertLengthToIpv4Mask pConvertLengthToIpv4Mask
125#else
126DWORD WINAPI ConvertGuidToStringA( const GUID *, char *, DWORD );
127DWORD WINAPI ConvertGuidToStringW( const GUID *, WCHAR *, DWORD );
128DWORD WINAPI ConvertStringToGuidW( const WCHAR *, GUID * );
129#endif
130
131static void loadIPHlpApi(void)
132{
133 hLibrary = LoadLibraryA("iphlpapi.dll");
134 if (hLibrary) {
135 pAllocateAndGetTcpExTableFromStack = (void *)GetProcAddress(hLibrary, "AllocateAndGetTcpExTableFromStack");
136 pGetTcp6Table = (void *)GetProcAddress(hLibrary, "GetTcp6Table");
137 pGetUdp6Table = (void *)GetProcAddress(hLibrary, "GetUdp6Table");
138 pGetUnicastIpAddressEntry = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressEntry");
139 pGetUnicastIpAddressTable = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressTable");
140 pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable");
141 pGetExtendedUdpTable = (void *)GetProcAddress(hLibrary, "GetExtendedUdpTable");
142 pCreateSortedAddressPairs = (void *)GetProcAddress(hLibrary, "CreateSortedAddressPairs");
143 pConvertLengthToIpv4Mask = (void *)GetProcAddress(hLibrary, "ConvertLengthToIpv4Mask");
144 pParseNetworkString = (void *)GetProcAddress(hLibrary, "ParseNetworkString");
145 pNotifyUnicastIpAddressChange = (void *)GetProcAddress(hLibrary, "NotifyUnicastIpAddressChange");
146 pCancelMibChangeNotify2 = (void *)GetProcAddress(hLibrary, "CancelMibChangeNotify2");
147#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
148 ConvertInterfaceAliasToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceAliasToLuid");
149 ConvertInterfaceLuidToAlias = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToAlias");
150 ConvertGuidToStringA = (void *)GetProcAddress(hLibrary, "ConvertGuidToStringA");
151 ConvertGuidToStringW = (void *)GetProcAddress(hLibrary, "ConvertGuidToStringW");
152 ConvertStringToGuidW = (void *)GetProcAddress(hLibrary, "ConvertStringToGuidW");
153 GetIfEntry2 = (void *)GetProcAddress(hLibrary, "GetIfEntry2");
154 GetIfTable2 = (void *)GetProcAddress(hLibrary, "GetIfTable2");
155 GetIfTable2Ex = (void *)GetProcAddress(hLibrary, "GetIfTable2Ex");
156 GetIpForwardTable2 = (void *)GetProcAddress(hLibrary, "GetIpForwardTable2");
157 GetIpNetTable2 = (void *)GetProcAddress(hLibrary, "GetIpNetTable2");
158 FreeMibTable = (void *)GetProcAddress(hLibrary, "FreeMibTable");
159 ConvertInterfaceGuidToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceGuidToLuid");
160 ConvertInterfaceIndexToLuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceIndexToLuid");
161 ConvertInterfaceLuidToGuid = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToGuid");
162 ConvertInterfaceLuidToIndex = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToIndex");
163 ConvertInterfaceLuidToNameA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameA");
164 ConvertInterfaceLuidToNameW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceLuidToNameW");
165 ConvertInterfaceNameToLuidA = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidA");
166 ConvertInterfaceNameToLuidW = (void *)GetProcAddress(hLibrary, "ConvertInterfaceNameToLuidW");
167 GetCurrentThreadCompartmentId = (void *)GetProcAddress(hLibrary, "GetCurrentThreadCompartmentId");
168 if_indextoname = (void *)GetProcAddress(hLibrary, "if_indextoname");
169 if_nametoindex = (void *)GetProcAddress(hLibrary, "if_nametoindex");
170
171 /* If we can't get FreeMibTable(), use free(). */
172 if (!FreeMibTable)
173 FreeMibTable = (void (WINAPI *)(void *))free;
174#endif
175 }
176}
177
178static void freeIPHlpApi(void)
179{
180 FreeLibrary(hLibrary);
181}
182
183/* replacement for inet_ntoa */
184static const char *ntoa( DWORD ip )
185{
186 static char buffers[4][16];
187 static int i = -1;
188
189 ip = htonl(ip);
190 i = (i + 1) % ARRAY_SIZE(buffers);
191 sprintf( buffers[i], "%lu.%lu.%lu.%lu", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff );
192 return buffers[i];
193}
194
195static const char *ntoa6( IN6_ADDR *ip )
196{
197 static char buffers[4][40];
198 static int i = -1;
199 unsigned short *p = ip->u.Word;
200
201 i = (i + 1) % ARRAY_SIZE(buffers);
202 sprintf( buffers[i], "%x:%x:%x:%x:%x:%x:%x:%x",
203 htons(p[0]), htons(p[1]), htons(p[2]), htons(p[3]), htons(p[4]), htons(p[5]), htons(p[6]), htons(p[7]) );
204 return buffers[i];
205}
206
207static DWORD ipv4_addr( BYTE b1, BYTE b2, BYTE b3, BYTE b4 )
208{
209 return htonl( (b1 << 24) | (b2 << 16) | (b3 << 8) | b4 );
210}
211
212/*
213still-to-be-tested 98-only functions:
214GetUniDirectionalAdapterInfo
215*/
216static void testWin98OnlyFunctions(void)
217{
218}
219
220static void testGetNumberOfInterfaces(void)
221{
222 DWORD apiReturn, numInterfaces;
223
224 /* Crashes on Vista */
225 if (0) {
226 apiReturn = GetNumberOfInterfaces(NULL);
227 if (apiReturn == ERROR_NOT_SUPPORTED)
228 return;
229 ok(apiReturn == ERROR_INVALID_PARAMETER,
230 "GetNumberOfInterfaces(NULL) returned %ld, expected ERROR_INVALID_PARAMETER\n",
231 apiReturn);
232 }
233
234 apiReturn = GetNumberOfInterfaces(&numInterfaces);
235 ok(apiReturn == NO_ERROR,
236 "GetNumberOfInterfaces returned %ld, expected 0\n", apiReturn);
237}
238
239static void testGetIfEntry(DWORD index)
240{
241 DWORD apiReturn;
242 MIB_IFROW row;
243
244 memset(&row, 0, sizeof(row));
245 apiReturn = GetIfEntry(NULL);
246 if (apiReturn == ERROR_NOT_SUPPORTED) {
247 skip("GetIfEntry is not supported\n");
248 return;
249 }
250 ok(apiReturn == ERROR_INVALID_PARAMETER,
251 "GetIfEntry(NULL) returned %ld, expected ERROR_INVALID_PARAMETER\n",
252 apiReturn);
253 row.dwIndex = -1; /* hope that's always bogus! */
254 apiReturn = GetIfEntry(&row);
255 ok(apiReturn == ERROR_INVALID_DATA ||
256 apiReturn == ERROR_FILE_NOT_FOUND /* Vista */,
257 "GetIfEntry(bogus row) returned %ld, expected ERROR_INVALID_DATA or ERROR_FILE_NOT_FOUND\n",
258 apiReturn);
259 row.dwIndex = index;
260 apiReturn = GetIfEntry(&row);
261 ok(apiReturn == NO_ERROR,
262 "GetIfEntry returned %ld, expected NO_ERROR\n", apiReturn);
263}
264
265static void testGetIpAddrTable(void)
266{
267 DWORD apiReturn;
268 ULONG dwSize = 0;
269
270 apiReturn = GetIpAddrTable(NULL, NULL, FALSE);
271 if (apiReturn == ERROR_NOT_SUPPORTED) {
272 skip("GetIpAddrTable is not supported\n");
273 return;
274 }
275 ok(apiReturn == ERROR_INVALID_PARAMETER,
276 "GetIpAddrTable(NULL, NULL, FALSE) returned %ld, expected ERROR_INVALID_PARAMETER\n",
277 apiReturn);
278 apiReturn = GetIpAddrTable(NULL, &dwSize, FALSE);
279 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
280 "GetIpAddrTable(NULL, &dwSize, FALSE) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
281 apiReturn);
282 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
283 PMIB_IPADDRTABLE buf = malloc(dwSize);
284
285 apiReturn = GetIpAddrTable(buf, &dwSize, FALSE);
286 ok(apiReturn == NO_ERROR,
287 "GetIpAddrTable(buf, &dwSize, FALSE) returned %ld, expected NO_ERROR\n",
288 apiReturn);
289 if (apiReturn == NO_ERROR && buf->dwNumEntries)
290 {
291 int i;
292 testGetIfEntry(buf->table[0].dwIndex);
293 for (i = 0; i < buf->dwNumEntries; i++)
294 {
295 ok (buf->table[i].wType != 0, "Test[%d]: expected wType > 0\n", i);
296 ok (buf->table[i].dwBCastAddr == 1, "Test[%d]: got %08lx\n", i, buf->table[i].dwBCastAddr);
297 ok (buf->table[i].dwReasmSize == 0xffff, "Test[%d]: got %08lx\n", i, buf->table[i].dwReasmSize);
298 trace("Entry[%d]: addr %s, dwIndex %lu, wType 0x%x\n", i,
299 ntoa(buf->table[i].dwAddr), buf->table[i].dwIndex, buf->table[i].wType);
300 }
301 }
302 free(buf);
303 }
304}
305
306static void testGetIfTable(void)
307{
308 DWORD apiReturn;
309 ULONG dwSize = 0;
310
311#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
312 if (!GetIfEntry2)
313 skip("Missing APIs!\n");
314#endif
315 apiReturn = GetIfTable(NULL, NULL, FALSE);
316 if (apiReturn == ERROR_NOT_SUPPORTED) {
317 skip("GetIfTable is not supported\n");
318 return;
319 }
320 ok(apiReturn == ERROR_INVALID_PARAMETER,
321 "GetIfTable(NULL, NULL, FALSE) returned %ld, expected ERROR_INVALID_PARAMETER\n",
322 apiReturn);
323 apiReturn = GetIfTable(NULL, &dwSize, FALSE);
324 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
325 "GetIfTable(NULL, &dwSize, FALSE) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
326 apiReturn);
327 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
328 PMIB_IFTABLE buf = malloc(dwSize);
329
330 apiReturn = GetIfTable(buf, &dwSize, FALSE);
331 ok(apiReturn == NO_ERROR,
332 "GetIfTable(buf, &dwSize, FALSE) returned %ld, expected NO_ERROR\n\n",
333 apiReturn);
334
335 if (apiReturn == NO_ERROR)
336 {
337 char descr[MAX_INTERFACE_NAME_LEN];
338 WCHAR name[MAX_INTERFACE_NAME_LEN];
339 DWORD i, index;
340
341 if (winetest_debug > 1) trace( "interface table: %lu entries\n", buf->dwNumEntries );
342#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
343 if (GetIfEntry2) {
344#endif
345 for (i = 0; i < buf->dwNumEntries; i++)
346 {
347 MIB_IFROW *row = &buf->table[i];
348 MIB_IF_ROW2 row2;
349 GUID *guid;
350
351 if (winetest_debug > 1)
352 {
353 trace( "%lu: '%s' type %lu mtu %lu speed %lu\n",
354 row->dwIndex, debugstr_w(row->wszName), row->dwType, row->dwMtu, row->dwSpeed );
355 trace( " in: bytes %lu upkts %lu nupkts %lu disc %lu err %lu unk %lu\n",
356 row->dwInOctets, row->dwInUcastPkts, row->dwInNUcastPkts,
357 row->dwInDiscards, row->dwInErrors, row->dwInUnknownProtos );
358 trace( " out: bytes %lu upkts %lu nupkts %lu disc %lu err %lu\n",
359 row->dwOutOctets, row->dwOutUcastPkts, row->dwOutNUcastPkts,
360 row->dwOutDiscards, row->dwOutErrors );
361 }
362 apiReturn = GetAdapterIndex( row->wszName, &index );
363 ok( !apiReturn, "got %ld\n", apiReturn );
364 ok( index == row->dwIndex ||
365 broken( index != row->dwIndex && index ), /* Win8 can have identical guids for two different ifaces */
366 "got %ld vs %ld\n", index, row->dwIndex );
367 memset( &row2, 0, sizeof(row2) );
368 row2.InterfaceIndex = row->dwIndex;
369 GetIfEntry2( &row2 );
370 WideCharToMultiByte( CP_ACP, 0, row2.Description, -1, descr, sizeof(descr), NULL, NULL );
371 ok( !strcmp( (char *)row->bDescr, descr ), "got %s vs %s\n", row->bDescr, descr );
372 guid = &row2.InterfaceGuid;
373#ifdef __REACTOS__
374 _snwprintf( name, ARRAY_SIZE(name), L"\\DEVICE\\TCPIP_{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
375 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
376 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
377 guid->Data4[6], guid->Data4[7]);
378#else
379 swprintf( name, ARRAY_SIZE(name), L"\\DEVICE\\TCPIP_{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
380 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
381 guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
382 guid->Data4[6], guid->Data4[7]);
383#endif
384 ok( !wcscmp( row->wszName, name ), "got %s vs %s\n", debugstr_w( row->wszName ), debugstr_w( name ) );
385 }
386#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
387 }
388#endif
389 }
390 free(buf);
391 }
392}
393
394static void testGetIpForwardTable(void)
395{
396 DWORD err, i, j;
397 ULONG size = 0;
398 MIB_IPFORWARDTABLE *buf;
399 MIB_IPFORWARD_TABLE2 *table2;
400 MIB_UNICASTIPADDRESS_TABLE *unicast;
401#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
402 if (!GetIpForwardTable2 || !GetUnicastIpAddressTable || !ConvertLengthToIpv4Mask) {
403 skip("Missing APIs!\n");
404 return;
405 }
406#endif
407
408 err = GetIpForwardTable( NULL, NULL, FALSE );
409 ok( err == ERROR_INVALID_PARAMETER, "got %ld\n", err );
410
411 err = GetIpForwardTable( NULL, &size, FALSE );
412 ok( err == ERROR_INSUFFICIENT_BUFFER, "got %ld\n", err );
413
414 buf = malloc( size );
415 err = GetIpForwardTable( buf, &size, FALSE );
416 ok( !err, "got %ld\n", err );
417
418 err = GetIpForwardTable2( AF_INET, &table2 );
419 ok( !err, "got %ld\n", err );
420 ok( buf->dwNumEntries == table2->NumEntries, "got %ld vs %ld\n",
421 buf->dwNumEntries, table2->NumEntries );
422
423 err = GetUnicastIpAddressTable( AF_INET, &unicast );
424 ok( !err, "got %ld\n", err );
425
426 trace( "IP forward table: %lu entries\n", buf->dwNumEntries );
427 for (i = 0; i < buf->dwNumEntries; i++)
428 {
429 MIB_IPFORWARDROW *row = buf->table + i;
430 MIB_IPFORWARD_ROW2 *row2 = table2->Table + i;
431 DWORD mask, next_hop;
432
433 winetest_push_context( "%ld", i );
434
435 trace( "dest %s mask %s gw %s if %lu type %lu proto %lu\n",
436 ntoa( row->dwForwardDest ), ntoa( row->dwForwardMask ),
437 ntoa( row->dwForwardNextHop ), row->dwForwardIfIndex,
438 row->dwForwardType, row->dwForwardProto );
439 ok( row->dwForwardDest == row2->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr,
440 "got %08lx vs %08lx\n", row->dwForwardDest, row2->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr );
441 ConvertLengthToIpv4Mask( row2->DestinationPrefix.PrefixLength, &mask );
442 ok( row->dwForwardMask == mask, "got %08lx vs %08lx\n", row->dwForwardMask, mask );
443 ok( row->dwForwardPolicy == 0, "got %ld\n", row->dwForwardPolicy );
444
445 next_hop = row2->NextHop.Ipv4.sin_addr.s_addr;
446 if (!next_hop) /* for direct addresses, dwForwardNextHop is set to the address of the appropriate interface */
447 {
448 for (j = 0; j < unicast->NumEntries; j++)
449 {
450 if (unicast->Table[j].InterfaceLuid.Value == row2->InterfaceLuid.Value)
451 {
452 next_hop = unicast->Table[j].Address.Ipv4.sin_addr.s_addr;
453 break;
454 }
455 }
456 }
457 ok( row->dwForwardNextHop == next_hop, "got %08lx vs %08lx\n", row->dwForwardNextHop, next_hop );
458
459 ok( row->dwForwardIfIndex == row2->InterfaceIndex, "got %ld vs %ld\n", row->dwForwardIfIndex, row2->InterfaceIndex );
460 if (!row2->NextHop.Ipv4.sin_addr.s_addr)
461 ok( buf->table[i].dwForwardType == MIB_IPROUTE_TYPE_DIRECT, "got %ld\n", buf->table[i].dwForwardType );
462 else
463 ok( buf->table[i].dwForwardType == MIB_IPROUTE_TYPE_INDIRECT, "got %ld\n", buf->table[i].dwForwardType );
464 ok( row->dwForwardProto == row2->Protocol, "got %ld vs %d\n", row->dwForwardProto, row2->Protocol );
465 ok( row->dwForwardAge == row2->Age || row->dwForwardAge + 1 == row2->Age,
466 "got %ld vs %ld\n", row->dwForwardAge, row2->Age );
467 ok( row->dwForwardNextHopAS == 0, "got %08lx\n", row->dwForwardNextHopAS );
468 /* FIXME: need to add the interface's metric from GetIpInterfaceTable() */
469 ok( row->dwForwardMetric1 >= row2->Metric, "got %ld vs %ld\n", row->dwForwardMetric1, row2->Metric );
470 ok( row->dwForwardMetric2 == 0, "got %ld\n", row->dwForwardMetric2 );
471 ok( row->dwForwardMetric3 == 0, "got %ld\n", row->dwForwardMetric3 );
472 ok( row->dwForwardMetric4 == 0, "got %ld\n", row->dwForwardMetric4 );
473 ok( row->dwForwardMetric5 == 0, "got %ld\n", row->dwForwardMetric5 );
474
475 winetest_pop_context();
476 }
477 FreeMibTable( unicast );
478 FreeMibTable( table2 );
479 free( buf );
480}
481
482static void testGetIpNetTable(void)
483{
484 DWORD apiReturn, ret, prev_idx;
485 BOOL igmp3_found, ssdp_found;
486 DWORD igmp3_addr, ssdp_addr;
487 MIB_IPNET_TABLE2 *table2;
488 ULONG dwSize = 0;
489 unsigned int i;
490#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
491 if (!GetIpNetTable2)
492 skip("Missing APIs!\n");
493#endif
494
495 igmp3_addr = ipv4_addr( 224, 0, 0, 22 );
496 ssdp_addr = ipv4_addr( 239, 255, 255, 250 );
497
498 apiReturn = GetIpNetTable(NULL, NULL, FALSE);
499 if (apiReturn == ERROR_NOT_SUPPORTED) {
500 skip("GetIpNetTable is not supported\n");
501 return;
502 }
503 ok(apiReturn == ERROR_INVALID_PARAMETER,
504 "GetIpNetTable(NULL, NULL, FALSE) returned %ld, expected ERROR_INVALID_PARAMETER\n",
505 apiReturn);
506 apiReturn = GetIpNetTable(NULL, &dwSize, FALSE);
507 ok(apiReturn == ERROR_NO_DATA || apiReturn == ERROR_INSUFFICIENT_BUFFER,
508 "GetIpNetTable(NULL, &dwSize, FALSE) returned %ld, expected ERROR_NO_DATA or ERROR_INSUFFICIENT_BUFFER\n",
509 apiReturn);
510 if (apiReturn == ERROR_NO_DATA)
511 ; /* empty ARP table's okay */
512 else if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
513 PMIB_IPNETTABLE buf = malloc(dwSize);
514
515 memset(buf, 0xcc, dwSize);
516 apiReturn = GetIpNetTable(buf, &dwSize, TRUE);
517 ok((apiReturn == NO_ERROR && buf->dwNumEntries) || (apiReturn == ERROR_NO_DATA && !buf->dwNumEntries),
518 "got apiReturn %lu, dwSize %lu, buf->dwNumEntries %lu.\n",
519 apiReturn, dwSize, buf->dwNumEntries);
520
521 if (apiReturn == NO_ERROR)
522 {
523 for (i = 0; i < buf->dwNumEntries - 1; ++i)
524 {
525 ok( buf->table[i].dwIndex <= buf->table[i + 1].dwIndex,
526 "Entries are not sorted by index, i %u.\n", i );
527 if (buf->table[i].dwIndex == buf->table[i + 1].dwIndex)
528 ok(ntohl(buf->table[i].dwAddr) <= ntohl(buf->table[i + 1].dwAddr),
529 "Entries are not sorted by address, i %u.\n", i );
530 }
531
532 igmp3_found = ssdp_found = FALSE;
533 prev_idx = ~0u;
534 for (i = 0; i < buf->dwNumEntries; ++i)
535 {
536 if (buf->table[i].dwIndex != prev_idx)
537 {
538 if (prev_idx != ~0u)
539 {
540 ok( igmp3_found, "%s not found, iface index %lu.\n", ntoa( igmp3_addr ), prev_idx);
541 ok( ssdp_found || broken(!ssdp_found) /* 239.255.255.250 is always present since Win10 */,
542 "%s not found.\n", ntoa( ssdp_addr ));
543 }
544 prev_idx = buf->table[i].dwIndex;
545 igmp3_found = ssdp_found = FALSE;
546 }
547 if (buf->table[i].dwAddr == igmp3_addr)
548 igmp3_found = TRUE;
549 else if (buf->table[i].dwAddr == ssdp_addr)
550 ssdp_found = TRUE;
551 }
552#if defined(__REACTOS__)
553 if (LOBYTE(LOWORD(GetVersion())) >= 6)
554#endif
555 ok( igmp3_found, "%s not found.\n", ntoa( igmp3_addr ));
556 ok( ssdp_found || broken(!ssdp_found) /* 239.255.255.250 is always present since Win10 */,
557 "%s not found.\n", ntoa( ssdp_addr ));
558
559#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
560 if(GetIpNetTable2) {
561#endif
562 ret = GetIpNetTable2( AF_INET, &table2 );
563 ok( !ret, "got ret %lu.\n", ret );
564 for (i = 0; i < table2->NumEntries; ++i)
565 {
566 MIB_IPNET_ROW2 *row = &table2->Table[i];
567 if (row->Address.Ipv4.sin_addr.s_addr == igmp3_addr
568 || row->Address.Ipv4.sin_addr.s_addr == ssdp_addr)
569 {
570 ok( row->State == NlnsPermanent, "got state %d.\n", row->State );
571 ok( !row->IsRouter, "IsRouter is set.\n" );
572 ok( !row->IsUnreachable, "IsUnreachable is set.\n" );
573 }
574 }
575 FreeMibTable( table2 );
576#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
577 }
578#endif
579 }
580
581 if (apiReturn == NO_ERROR && winetest_debug > 1)
582 {
583 DWORD i, j;
584
585 trace( "IP net table: %lu entries\n", buf->dwNumEntries );
586 for (i = 0; i < buf->dwNumEntries; i++)
587 {
588 trace( "%lu: idx %lu type %lu addr %s phys",
589 i, buf->table[i].dwIndex, buf->table[i].dwType, ntoa( buf->table[i].dwAddr ));
590 for (j = 0; j < buf->table[i].dwPhysAddrLen; j++)
591 printf( " %02x", buf->table[i].bPhysAddr[j] );
592 printf( "\n" );
593 }
594 }
595 free(buf);
596 }
597}
598
599static void testGetIcmpStatistics(void)
600{
601 DWORD apiReturn;
602 MIB_ICMP stats;
603
604 /* Crashes on Vista */
605 if (0) {
606 apiReturn = GetIcmpStatistics(NULL);
607 if (apiReturn == ERROR_NOT_SUPPORTED)
608 return;
609 ok(apiReturn == ERROR_INVALID_PARAMETER,
610 "GetIcmpStatistics(NULL) returned %ld, expected ERROR_INVALID_PARAMETER\n",
611 apiReturn);
612 }
613
614 apiReturn = GetIcmpStatistics(&stats);
615 if (apiReturn == ERROR_NOT_SUPPORTED)
616 {
617 skip("GetIcmpStatistics is not supported\n");
618 return;
619 }
620 ok(apiReturn == NO_ERROR,
621 "GetIcmpStatistics returned %ld, expected NO_ERROR\n", apiReturn);
622 if (apiReturn == NO_ERROR && winetest_debug > 1)
623 {
624 trace( "ICMP stats: %8s %8s\n", "in", "out" );
625 trace( " dwMsgs: %8lu %8lu\n", stats.stats.icmpInStats.dwMsgs, stats.stats.icmpOutStats.dwMsgs );
626 trace( " dwErrors: %8lu %8lu\n", stats.stats.icmpInStats.dwErrors, stats.stats.icmpOutStats.dwErrors );
627 trace( " dwDestUnreachs: %8lu %8lu\n", stats.stats.icmpInStats.dwDestUnreachs, stats.stats.icmpOutStats.dwDestUnreachs );
628 trace( " dwTimeExcds: %8lu %8lu\n", stats.stats.icmpInStats.dwTimeExcds, stats.stats.icmpOutStats.dwTimeExcds );
629 trace( " dwParmProbs: %8lu %8lu\n", stats.stats.icmpInStats.dwParmProbs, stats.stats.icmpOutStats.dwParmProbs );
630 trace( " dwSrcQuenchs: %8lu %8lu\n", stats.stats.icmpInStats.dwSrcQuenchs, stats.stats.icmpOutStats.dwSrcQuenchs );
631 trace( " dwRedirects: %8lu %8lu\n", stats.stats.icmpInStats.dwRedirects, stats.stats.icmpOutStats.dwRedirects );
632 trace( " dwEchos: %8lu %8lu\n", stats.stats.icmpInStats.dwEchos, stats.stats.icmpOutStats.dwEchos );
633 trace( " dwEchoReps: %8lu %8lu\n", stats.stats.icmpInStats.dwEchoReps, stats.stats.icmpOutStats.dwEchoReps );
634 trace( " dwTimestamps: %8lu %8lu\n", stats.stats.icmpInStats.dwTimestamps, stats.stats.icmpOutStats.dwTimestamps );
635 trace( " dwTimestampReps: %8lu %8lu\n", stats.stats.icmpInStats.dwTimestampReps, stats.stats.icmpOutStats.dwTimestampReps );
636 trace( " dwAddrMasks: %8lu %8lu\n", stats.stats.icmpInStats.dwAddrMasks, stats.stats.icmpOutStats.dwAddrMasks );
637 trace( " dwAddrMaskReps: %8lu %8lu\n", stats.stats.icmpInStats.dwAddrMaskReps, stats.stats.icmpOutStats.dwAddrMaskReps );
638 }
639}
640
641static void testGetIpStatistics(void)
642{
643 DWORD apiReturn;
644 MIB_IPSTATS stats;
645
646 apiReturn = GetIpStatistics(NULL);
647 if (apiReturn == ERROR_NOT_SUPPORTED) {
648 skip("GetIpStatistics is not supported\n");
649 return;
650 }
651 ok(apiReturn == ERROR_INVALID_PARAMETER,
652 "GetIpStatistics(NULL) returned %ld, expected ERROR_INVALID_PARAMETER\n",
653 apiReturn);
654 apiReturn = GetIpStatistics(&stats);
655 ok(apiReturn == NO_ERROR,
656 "GetIpStatistics returned %ld, expected NO_ERROR\n", apiReturn);
657 if (apiReturn == NO_ERROR && winetest_debug > 1)
658 {
659 trace( "IP stats:\n" );
660 trace( " dwForwarding: %lu\n", stats.dwForwarding );
661 trace( " dwDefaultTTL: %lu\n", stats.dwDefaultTTL );
662 trace( " dwInReceives: %lu\n", stats.dwInReceives );
663 trace( " dwInHdrErrors: %lu\n", stats.dwInHdrErrors );
664 trace( " dwInAddrErrors: %lu\n", stats.dwInAddrErrors );
665 trace( " dwForwDatagrams: %lu\n", stats.dwForwDatagrams );
666 trace( " dwInUnknownProtos: %lu\n", stats.dwInUnknownProtos );
667 trace( " dwInDiscards: %lu\n", stats.dwInDiscards );
668 trace( " dwInDelivers: %lu\n", stats.dwInDelivers );
669 trace( " dwOutRequests: %lu\n", stats.dwOutRequests );
670 trace( " dwRoutingDiscards: %lu\n", stats.dwRoutingDiscards );
671 trace( " dwOutDiscards: %lu\n", stats.dwOutDiscards );
672 trace( " dwOutNoRoutes: %lu\n", stats.dwOutNoRoutes );
673 trace( " dwReasmTimeout: %lu\n", stats.dwReasmTimeout );
674 trace( " dwReasmReqds: %lu\n", stats.dwReasmReqds );
675 trace( " dwReasmOks: %lu\n", stats.dwReasmOks );
676 trace( " dwReasmFails: %lu\n", stats.dwReasmFails );
677 trace( " dwFragOks: %lu\n", stats.dwFragOks );
678 trace( " dwFragFails: %lu\n", stats.dwFragFails );
679 trace( " dwFragCreates: %lu\n", stats.dwFragCreates );
680 trace( " dwNumIf: %lu\n", stats.dwNumIf );
681 trace( " dwNumAddr: %lu\n", stats.dwNumAddr );
682 trace( " dwNumRoutes: %lu\n", stats.dwNumRoutes );
683 }
684}
685
686static void testGetTcpStatistics(void)
687{
688 DWORD apiReturn;
689 MIB_TCPSTATS stats;
690
691 apiReturn = GetTcpStatistics(NULL);
692 if (apiReturn == ERROR_NOT_SUPPORTED) {
693 skip("GetTcpStatistics is not supported\n");
694 return;
695 }
696 ok(apiReturn == ERROR_INVALID_PARAMETER,
697 "GetTcpStatistics(NULL) returned %ld, expected ERROR_INVALID_PARAMETER\n",
698 apiReturn);
699 apiReturn = GetTcpStatistics(&stats);
700 ok(apiReturn == NO_ERROR,
701 "GetTcpStatistics returned %ld, expected NO_ERROR\n", apiReturn);
702 if (apiReturn == NO_ERROR && winetest_debug > 1)
703 {
704 trace( "TCP stats:\n" );
705 trace( " dwRtoAlgorithm: %lu\n", stats.dwRtoAlgorithm );
706 trace( " dwRtoMin: %lu\n", stats.dwRtoMin );
707 trace( " dwRtoMax: %lu\n", stats.dwRtoMax );
708 trace( " dwMaxConn: %lu\n", stats.dwMaxConn );
709 trace( " dwActiveOpens: %lu\n", stats.dwActiveOpens );
710 trace( " dwPassiveOpens: %lu\n", stats.dwPassiveOpens );
711 trace( " dwAttemptFails: %lu\n", stats.dwAttemptFails );
712 trace( " dwEstabResets: %lu\n", stats.dwEstabResets );
713 trace( " dwCurrEstab: %lu\n", stats.dwCurrEstab );
714 trace( " dwInSegs: %lu\n", stats.dwInSegs );
715 trace( " dwOutSegs: %lu\n", stats.dwOutSegs );
716 trace( " dwRetransSegs: %lu\n", stats.dwRetransSegs );
717 trace( " dwInErrs: %lu\n", stats.dwInErrs );
718 trace( " dwOutRsts: %lu\n", stats.dwOutRsts );
719 trace( " dwNumConns: %lu\n", stats.dwNumConns );
720 }
721}
722
723static void testGetUdpStatistics(void)
724{
725 DWORD apiReturn;
726 MIB_UDPSTATS stats;
727
728 apiReturn = GetUdpStatistics(NULL);
729 if (apiReturn == ERROR_NOT_SUPPORTED) {
730 skip("GetUdpStatistics is not supported\n");
731 return;
732 }
733 ok(apiReturn == ERROR_INVALID_PARAMETER,
734 "GetUdpStatistics(NULL) returned %ld, expected ERROR_INVALID_PARAMETER\n",
735 apiReturn);
736 apiReturn = GetUdpStatistics(&stats);
737 ok(apiReturn == NO_ERROR,
738 "GetUdpStatistics returned %ld, expected NO_ERROR\n", apiReturn);
739 if (apiReturn == NO_ERROR && winetest_debug > 1)
740 {
741 trace( "UDP stats:\n" );
742 trace( " dwInDatagrams: %lu\n", stats.dwInDatagrams );
743 trace( " dwNoPorts: %lu\n", stats.dwNoPorts );
744 trace( " dwInErrors: %lu\n", stats.dwInErrors );
745 trace( " dwOutDatagrams: %lu\n", stats.dwOutDatagrams );
746 trace( " dwNumAddrs: %lu\n", stats.dwNumAddrs );
747 }
748}
749
750static void testGetIcmpStatisticsEx(void)
751{
752 DWORD apiReturn;
753 MIB_ICMP_EX stats;
754
755 /* Crashes on Vista */
756 if (1) {
757 apiReturn = GetIcmpStatisticsEx(NULL, AF_INET);
758 ok(apiReturn == ERROR_INVALID_PARAMETER,
759 "GetIcmpStatisticsEx(NULL, AF_INET) returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
760 }
761
762 apiReturn = GetIcmpStatisticsEx(&stats, AF_BAN);
763 ok(apiReturn == ERROR_INVALID_PARAMETER,
764 "GetIcmpStatisticsEx(&stats, AF_BAN) returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
765
766 apiReturn = GetIcmpStatisticsEx(&stats, AF_INET);
767 ok(apiReturn == NO_ERROR, "GetIcmpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
768 if (apiReturn == NO_ERROR && winetest_debug > 1)
769 {
770 INT i;
771 trace( "ICMP IPv4 Ex stats: %8s %8s\n", "in", "out" );
772 trace( " dwMsgs: %8lu %8lu\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
773 trace( " dwErrors: %8lu %8lu\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
774 for (i = 0; i < 256; i++)
775 trace( " rgdwTypeCount[%3i]: %8lu %8lu\n", i, stats.icmpInStats.rgdwTypeCount[i], stats.icmpOutStats.rgdwTypeCount[i] );
776 }
777
778 apiReturn = GetIcmpStatisticsEx(&stats, AF_INET6);
779 ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
780 "GetIcmpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
781 if (apiReturn == NO_ERROR && winetest_debug > 1)
782 {
783 INT i;
784 trace( "ICMP IPv6 Ex stats: %8s %8s\n", "in", "out" );
785 trace( " dwMsgs: %8lu %8lu\n", stats.icmpInStats.dwMsgs, stats.icmpOutStats.dwMsgs );
786 trace( " dwErrors: %8lu %8lu\n", stats.icmpInStats.dwErrors, stats.icmpOutStats.dwErrors );
787 for (i = 0; i < 256; i++)
788 trace( " rgdwTypeCount[%3i]: %8lu %8lu\n", i, stats.icmpInStats.rgdwTypeCount[i], stats.icmpOutStats.rgdwTypeCount[i] );
789 }
790}
791
792static void testGetIpStatisticsEx(void)
793{
794 DWORD apiReturn;
795 MIB_IPSTATS stats;
796
797 apiReturn = GetIpStatisticsEx(NULL, AF_INET);
798 ok(apiReturn == ERROR_INVALID_PARAMETER,
799 "GetIpStatisticsEx(NULL, AF_INET) returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
800
801 apiReturn = GetIpStatisticsEx(&stats, AF_BAN);
802 ok(apiReturn == ERROR_INVALID_PARAMETER,
803 "GetIpStatisticsEx(&stats, AF_BAN) returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
804
805 apiReturn = GetIpStatisticsEx(&stats, AF_INET);
806 ok(apiReturn == NO_ERROR, "GetIpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
807 if (apiReturn == NO_ERROR && winetest_debug > 1)
808 {
809 trace( "IP IPv4 Ex stats:\n" );
810 trace( " dwForwarding: %lu\n", stats.dwForwarding );
811 trace( " dwDefaultTTL: %lu\n", stats.dwDefaultTTL );
812 trace( " dwInReceives: %lu\n", stats.dwInReceives );
813 trace( " dwInHdrErrors: %lu\n", stats.dwInHdrErrors );
814 trace( " dwInAddrErrors: %lu\n", stats.dwInAddrErrors );
815 trace( " dwForwDatagrams: %lu\n", stats.dwForwDatagrams );
816 trace( " dwInUnknownProtos: %lu\n", stats.dwInUnknownProtos );
817 trace( " dwInDiscards: %lu\n", stats.dwInDiscards );
818 trace( " dwInDelivers: %lu\n", stats.dwInDelivers );
819 trace( " dwOutRequests: %lu\n", stats.dwOutRequests );
820 trace( " dwRoutingDiscards: %lu\n", stats.dwRoutingDiscards );
821 trace( " dwOutDiscards: %lu\n", stats.dwOutDiscards );
822 trace( " dwOutNoRoutes: %lu\n", stats.dwOutNoRoutes );
823 trace( " dwReasmTimeout: %lu\n", stats.dwReasmTimeout );
824 trace( " dwReasmReqds: %lu\n", stats.dwReasmReqds );
825 trace( " dwReasmOks: %lu\n", stats.dwReasmOks );
826 trace( " dwReasmFails: %lu\n", stats.dwReasmFails );
827 trace( " dwFragOks: %lu\n", stats.dwFragOks );
828 trace( " dwFragFails: %lu\n", stats.dwFragFails );
829 trace( " dwFragCreates: %lu\n", stats.dwFragCreates );
830 trace( " dwNumIf: %lu\n", stats.dwNumIf );
831 trace( " dwNumAddr: %lu\n", stats.dwNumAddr );
832 trace( " dwNumRoutes: %lu\n", stats.dwNumRoutes );
833 }
834
835 apiReturn = GetIpStatisticsEx(&stats, AF_INET6);
836 ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
837 "GetIpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
838 if (apiReturn == NO_ERROR && winetest_debug > 1)
839 {
840 trace( "IP IPv6 Ex stats:\n" );
841 trace( " dwForwarding: %lu\n", stats.dwForwarding );
842 trace( " dwDefaultTTL: %lu\n", stats.dwDefaultTTL );
843 trace( " dwInReceives: %lu\n", stats.dwInReceives );
844 trace( " dwInHdrErrors: %lu\n", stats.dwInHdrErrors );
845 trace( " dwInAddrErrors: %lu\n", stats.dwInAddrErrors );
846 trace( " dwForwDatagrams: %lu\n", stats.dwForwDatagrams );
847 trace( " dwInUnknownProtos: %lu\n", stats.dwInUnknownProtos );
848 trace( " dwInDiscards: %lu\n", stats.dwInDiscards );
849 trace( " dwInDelivers: %lu\n", stats.dwInDelivers );
850 trace( " dwOutRequests: %lu\n", stats.dwOutRequests );
851 trace( " dwRoutingDiscards: %lu\n", stats.dwRoutingDiscards );
852 trace( " dwOutDiscards: %lu\n", stats.dwOutDiscards );
853 trace( " dwOutNoRoutes: %lu\n", stats.dwOutNoRoutes );
854 trace( " dwReasmTimeout: %lu\n", stats.dwReasmTimeout );
855 trace( " dwReasmReqds: %lu\n", stats.dwReasmReqds );
856 trace( " dwReasmOks: %lu\n", stats.dwReasmOks );
857 trace( " dwReasmFails: %lu\n", stats.dwReasmFails );
858 trace( " dwFragOks: %lu\n", stats.dwFragOks );
859 trace( " dwFragFails: %lu\n", stats.dwFragFails );
860 trace( " dwFragCreates: %lu\n", stats.dwFragCreates );
861 trace( " dwNumIf: %lu\n", stats.dwNumIf );
862 trace( " dwNumAddr: %lu\n", stats.dwNumAddr );
863 trace( " dwNumRoutes: %lu\n", stats.dwNumRoutes );
864 }
865}
866
867static void testGetTcpStatisticsEx(void)
868{
869 DWORD apiReturn;
870 MIB_TCPSTATS stats;
871
872 apiReturn = GetTcpStatisticsEx(NULL, AF_INET);
873 ok(apiReturn == ERROR_INVALID_PARAMETER,
874 "GetTcpStatisticsEx(NULL, AF_INET); returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
875
876 apiReturn = GetTcpStatisticsEx(&stats, AF_BAN);
877 ok(apiReturn == ERROR_INVALID_PARAMETER || apiReturn == ERROR_NOT_SUPPORTED,
878 "GetTcpStatisticsEx(&stats, AF_BAN) returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
879
880 apiReturn = GetTcpStatisticsEx(&stats, AF_INET);
881 ok(apiReturn == NO_ERROR, "GetTcpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
882 if (apiReturn == NO_ERROR && winetest_debug > 1)
883 {
884 trace( "TCP IPv4 Ex stats:\n" );
885 trace( " dwRtoAlgorithm: %lu\n", stats.dwRtoAlgorithm );
886 trace( " dwRtoMin: %lu\n", stats.dwRtoMin );
887 trace( " dwRtoMax: %lu\n", stats.dwRtoMax );
888 trace( " dwMaxConn: %lu\n", stats.dwMaxConn );
889 trace( " dwActiveOpens: %lu\n", stats.dwActiveOpens );
890 trace( " dwPassiveOpens: %lu\n", stats.dwPassiveOpens );
891 trace( " dwAttemptFails: %lu\n", stats.dwAttemptFails );
892 trace( " dwEstabResets: %lu\n", stats.dwEstabResets );
893 trace( " dwCurrEstab: %lu\n", stats.dwCurrEstab );
894 trace( " dwInSegs: %lu\n", stats.dwInSegs );
895 trace( " dwOutSegs: %lu\n", stats.dwOutSegs );
896 trace( " dwRetransSegs: %lu\n", stats.dwRetransSegs );
897 trace( " dwInErrs: %lu\n", stats.dwInErrs );
898 trace( " dwOutRsts: %lu\n", stats.dwOutRsts );
899 trace( " dwNumConns: %lu\n", stats.dwNumConns );
900 }
901
902 apiReturn = GetTcpStatisticsEx(&stats, AF_INET6);
903 ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
904 "GetTcpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
905 if (apiReturn == NO_ERROR && winetest_debug > 1)
906 {
907 trace( "TCP IPv6 Ex stats:\n" );
908 trace( " dwRtoAlgorithm: %lu\n", stats.dwRtoAlgorithm );
909 trace( " dwRtoMin: %lu\n", stats.dwRtoMin );
910 trace( " dwRtoMax: %lu\n", stats.dwRtoMax );
911 trace( " dwMaxConn: %lu\n", stats.dwMaxConn );
912 trace( " dwActiveOpens: %lu\n", stats.dwActiveOpens );
913 trace( " dwPassiveOpens: %lu\n", stats.dwPassiveOpens );
914 trace( " dwAttemptFails: %lu\n", stats.dwAttemptFails );
915 trace( " dwEstabResets: %lu\n", stats.dwEstabResets );
916 trace( " dwCurrEstab: %lu\n", stats.dwCurrEstab );
917 trace( " dwInSegs: %lu\n", stats.dwInSegs );
918 trace( " dwOutSegs: %lu\n", stats.dwOutSegs );
919 trace( " dwRetransSegs: %lu\n", stats.dwRetransSegs );
920 trace( " dwInErrs: %lu\n", stats.dwInErrs );
921 trace( " dwOutRsts: %lu\n", stats.dwOutRsts );
922 trace( " dwNumConns: %lu\n", stats.dwNumConns );
923 }
924}
925
926static void testGetUdpStatisticsEx(void)
927{
928 DWORD apiReturn;
929 MIB_UDPSTATS stats;
930
931 apiReturn = GetUdpStatisticsEx(NULL, AF_INET);
932 ok(apiReturn == ERROR_INVALID_PARAMETER,
933 "GetUdpStatisticsEx(NULL, AF_INET); returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
934
935 apiReturn = GetUdpStatisticsEx(&stats, AF_BAN);
936 ok(apiReturn == ERROR_INVALID_PARAMETER || apiReturn == ERROR_NOT_SUPPORTED,
937 "GetUdpStatisticsEx(&stats, AF_BAN) returned %ld, expected ERROR_INVALID_PARAMETER\n", apiReturn);
938
939 apiReturn = GetUdpStatisticsEx(&stats, AF_INET);
940 ok(apiReturn == NO_ERROR, "GetUdpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
941 if (apiReturn == NO_ERROR && winetest_debug > 1)
942 {
943 trace( "UDP IPv4 Ex stats:\n" );
944 trace( " dwInDatagrams: %lu\n", stats.dwInDatagrams );
945 trace( " dwNoPorts: %lu\n", stats.dwNoPorts );
946 trace( " dwInErrors: %lu\n", stats.dwInErrors );
947 trace( " dwOutDatagrams: %lu\n", stats.dwOutDatagrams );
948 trace( " dwNumAddrs: %lu\n", stats.dwNumAddrs );
949 }
950
951 apiReturn = GetUdpStatisticsEx(&stats, AF_INET6);
952 ok(apiReturn == NO_ERROR || broken(apiReturn == ERROR_NOT_SUPPORTED),
953 "GetUdpStatisticsEx returned %ld, expected NO_ERROR\n", apiReturn);
954 if (apiReturn == NO_ERROR && winetest_debug > 1)
955 {
956 trace( "UDP IPv6 Ex stats:\n" );
957 trace( " dwInDatagrams: %lu\n", stats.dwInDatagrams );
958 trace( " dwNoPorts: %lu\n", stats.dwNoPorts );
959 trace( " dwInErrors: %lu\n", stats.dwInErrors );
960 trace( " dwOutDatagrams: %lu\n", stats.dwOutDatagrams );
961 trace( " dwNumAddrs: %lu\n", stats.dwNumAddrs );
962 }
963}
964
965static void testGetTcpTable(void)
966{
967 DWORD apiReturn;
968 ULONG dwSize = 0;
969
970 apiReturn = GetTcpTable(NULL, &dwSize, FALSE);
971 if (apiReturn == ERROR_NOT_SUPPORTED) {
972 skip("GetTcpTable is not supported\n");
973 return;
974 }
975 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
976 "GetTcpTable(NULL, &dwSize, FALSE) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
977 apiReturn);
978 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
979 PMIB_TCPTABLE buf = malloc(dwSize);
980
981 apiReturn = GetTcpTable(buf, &dwSize, FALSE);
982 ok(apiReturn == NO_ERROR,
983 "GetTcpTable(buf, &dwSize, FALSE) returned %ld, expected NO_ERROR\n",
984 apiReturn);
985
986 if (apiReturn == NO_ERROR && winetest_debug > 1)
987 {
988 DWORD i;
989 trace( "TCP table: %lu entries\n", buf->dwNumEntries );
990 for (i = 0; i < buf->dwNumEntries; i++)
991 {
992 trace( "%lu: local %s:%u remote %s:%u state %lu\n", i,
993 ntoa(buf->table[i].dwLocalAddr), ntohs(buf->table[i].dwLocalPort),
994 ntoa(buf->table[i].dwRemoteAddr), ntohs(buf->table[i].dwRemotePort),
995 buf->table[i].dwState );
996 }
997 }
998 free(buf);
999 }
1000}
1001
1002static void testGetUdpTable(void)
1003{
1004 DWORD apiReturn;
1005 ULONG dwSize = 0;
1006
1007 apiReturn = GetUdpTable(NULL, &dwSize, FALSE);
1008 if (apiReturn == ERROR_NOT_SUPPORTED) {
1009 skip("GetUdpTable is not supported\n");
1010 return;
1011 }
1012 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
1013 "GetUdpTable(NULL, &dwSize, FALSE) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
1014 apiReturn);
1015 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
1016 PMIB_UDPTABLE buf = malloc(dwSize);
1017
1018 apiReturn = GetUdpTable(buf, &dwSize, FALSE);
1019 ok(apiReturn == NO_ERROR,
1020 "GetUdpTable(buf, &dwSize, FALSE) returned %ld, expected NO_ERROR\n",
1021 apiReturn);
1022
1023 if (apiReturn == NO_ERROR && winetest_debug > 1)
1024 {
1025 DWORD i;
1026 trace( "UDP table: %lu entries\n", buf->dwNumEntries );
1027 for (i = 0; i < buf->dwNumEntries; i++)
1028 trace( "%lu: %s:%u\n",
1029 i, ntoa( buf->table[i].dwLocalAddr ), ntohs(buf->table[i].dwLocalPort) );
1030 }
1031 free(buf);
1032 }
1033}
1034
1035static void testSetTcpEntry(void)
1036{
1037 DWORD ret;
1038 MIB_TCPROW row;
1039
1040 memset(&row, 0, sizeof(row));
1041 if(0) /* This test crashes in OS >= VISTA */
1042 {
1043 ret = SetTcpEntry(NULL);
1044 ok( ret == ERROR_INVALID_PARAMETER, "got %lu, expected %u\n", ret, ERROR_INVALID_PARAMETER);
1045 }
1046
1047 ret = SetTcpEntry(&row);
1048 if (ret == ERROR_NETWORK_ACCESS_DENIED)
1049 {
1050 win_skip("SetTcpEntry failed with access error. Skipping test.\n");
1051 return;
1052 }
1053 todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %lu, expected %u\n", ret, ERROR_INVALID_PARAMETER);
1054
1055 row.dwState = MIB_TCP_STATE_DELETE_TCB;
1056 ret = SetTcpEntry(&row);
1057 todo_wine ok( ret == ERROR_MR_MID_NOT_FOUND || broken(ret == ERROR_INVALID_PARAMETER),
1058 "got %lu, expected %u\n", ret, ERROR_MR_MID_NOT_FOUND);
1059}
1060
1061static BOOL icmp_send_echo_test_apc_expect;
1062static void WINAPI icmp_send_echo_test_apc_xp(void *context)
1063{
1064 ok(icmp_send_echo_test_apc_expect, "Unexpected APC execution\n");
1065 ok(context == (void*)0xdeadc0de, "Wrong context: %p\n", context);
1066 icmp_send_echo_test_apc_expect = FALSE;
1067}
1068
1069static void WINAPI icmp_send_echo_test_apc(void *context, IO_STATUS_BLOCK *io_status, ULONG reserved)
1070{
1071 icmp_send_echo_test_apc_xp(context);
1072 ok(io_status->Status == 0, "Got IO Status 0x%08lx\n", io_status->Status);
1073 ok(io_status->Information == sizeof(ICMP_ECHO_REPLY) + 32 /* sizeof(senddata) */,
1074 "Got IO Information %Iu\n", io_status->Information);
1075}
1076
1077static void testIcmpSendEcho(void)
1078{
1079 /* The APC's signature is different pre-Vista */
1080 const PIO_APC_ROUTINE apc = broken(LOBYTE(LOWORD(GetVersion())) < 6)
1081 ? (PIO_APC_ROUTINE)icmp_send_echo_test_apc_xp
1082 : icmp_send_echo_test_apc;
1083 HANDLE icmp;
1084 char senddata[32], replydata[sizeof(senddata) + sizeof(ICMP_ECHO_REPLY)];
1085 char replydata2[sizeof(replydata) + sizeof(IO_STATUS_BLOCK)];
1086 DWORD ret, error, replysz = sizeof(replydata);
1087 IPAddr address;
1088 ICMP_ECHO_REPLY *reply;
1089 HANDLE event;
1090 INT i;
1091
1092 memset(senddata, 0, sizeof(senddata));
1093
1094 address = htonl(INADDR_LOOPBACK);
1095 SetLastError(0xdeadbeef);
1096 ret = IcmpSendEcho(INVALID_HANDLE_VALUE, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1097 error = GetLastError();
1098 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1099 ok (error == ERROR_INVALID_PARAMETER
1100 || broken(error == ERROR_INVALID_HANDLE) /* <= 2003 */,
1101 "expected 87, got %ld\n", error);
1102
1103 address = htonl(INADDR_LOOPBACK);
1104 SetLastError(0xdeadbeef);
1105 ret = IcmpSendEcho2(INVALID_HANDLE_VALUE, NULL, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1106 error = GetLastError();
1107 ok (!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1108 ok (error == ERROR_INVALID_PARAMETER
1109 || broken(error == ERROR_INVALID_HANDLE) /* <= 2003 */,
1110 "expected 87, got %ld\n", error);
1111
1112 icmp = IcmpCreateFile();
1113 ok (icmp != INVALID_HANDLE_VALUE, "IcmpCreateFile failed unexpectedly with error %ld\n", GetLastError());
1114
1115 address = 0;
1116 SetLastError(0xdeadbeef);
1117 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1118 error = GetLastError();
1119 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1120 ok (error == ERROR_INVALID_NETNAME
1121 || broken(error == IP_BAD_DESTINATION) /* <= 2003 */,
1122 "expected 1214, got %ld\n", error);
1123
1124 address = htonl(INADDR_LOOPBACK);
1125 if (0) /* crashes in XP */
1126 {
1127 ret = IcmpSendEcho(icmp, address, NULL, sizeof(senddata), NULL, replydata, replysz, 1000);
1128 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1129 }
1130
1131 SetLastError(0xdeadbeef);
1132 ret = IcmpSendEcho(icmp, address, senddata, 0, NULL, replydata, replysz, 1000);
1133 error = GetLastError();
1134 if (!ret && error == ERROR_ACCESS_DENIED)
1135 {
1136 skip( "ICMP is not available.\n" );
1137 return;
1138 }
1139 ok (ret, "IcmpSendEcho failed unexpectedly with error %ld\n", error);
1140
1141 SetLastError(0xdeadbeef);
1142 ret = IcmpSendEcho(icmp, address, NULL, 0, NULL, replydata, replysz, 1000);
1143 error = GetLastError();
1144 ok (ret, "IcmpSendEcho failed unexpectedly with error %ld\n", error);
1145
1146 SetLastError(0xdeadbeef);
1147 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, NULL, replysz, 1000);
1148 error = GetLastError();
1149 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1150 ok (error == ERROR_INVALID_PARAMETER, "expected 87, got %ld\n", error);
1151
1152 SetLastError(0xdeadbeef);
1153 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, 0, 1000);
1154 error = GetLastError();
1155 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1156 ok (error == ERROR_INVALID_PARAMETER
1157 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1158 "expected 87, got %ld\n", error);
1159
1160 SetLastError(0xdeadbeef);
1161 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, NULL, 0, 1000);
1162 error = GetLastError();
1163 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1164 ok (error == ERROR_INVALID_PARAMETER
1165 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1166 "expected 87, got %ld\n", error);
1167
1168 SetLastError(0xdeadbeef);
1169 replysz = sizeof(replydata) - 1;
1170 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1171 error = GetLastError();
1172 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1173 ok (error == IP_GENERAL_FAILURE
1174 || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1175 "expected 11050, got %ld\n", error);
1176
1177 SetLastError(0xdeadbeef);
1178 replysz = sizeof(ICMP_ECHO_REPLY);
1179 ret = IcmpSendEcho(icmp, address, senddata, 0, NULL, replydata, replysz, 1000);
1180 error = GetLastError();
1181 ok (ret, "IcmpSendEcho failed unexpectedly with error %ld\n", error);
1182
1183 SetLastError(0xdeadbeef);
1184 replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
1185 ret = IcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz, 1000);
1186 error = GetLastError();
1187 ok (ret, "IcmpSendEcho failed unexpectedly with error %ld\n", error);
1188
1189 SetLastError(0xdeadbeef);
1190 replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
1191 ret = IcmpSendEcho(icmp, address, senddata, ICMP_MINLEN + 1, NULL, replydata, replysz, 1000);
1192 error = GetLastError();
1193 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1194 ok (error == IP_GENERAL_FAILURE
1195 || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1196 "expected 11050, got %ld\n", error);
1197
1198 SetLastError(0xdeadbeef);
1199 ret = IcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz - 1, 1000);
1200 error = GetLastError();
1201 ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
1202 ok (error == IP_GENERAL_FAILURE
1203 || broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
1204 "expected 11050, got %ld\n", error);
1205
1206 /* in windows >= vista the timeout can't be invalid */
1207 SetLastError(0xdeadbeef);
1208 replysz = sizeof(replydata);
1209 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 0);
1210 error = GetLastError();
1211 if (!ret) ok(error == ERROR_INVALID_PARAMETER, "expected 87, got %ld\n", error);
1212
1213 SetLastError(0xdeadbeef);
1214 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, -1);
1215 error = GetLastError();
1216 if (!ret) ok(error == ERROR_INVALID_PARAMETER, "expected 87, got %ld\n", error);
1217
1218 /* real ping test */
1219 SetLastError(0xdeadbeef);
1220 address = htonl(INADDR_LOOPBACK);
1221 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1222 error = GetLastError();
1223 if (!ret)
1224 {
1225 skip ("Failed to ping with error %ld, is lo interface down?.\n", error);
1226 }
1227 else if (winetest_debug > 1)
1228 {
1229 PICMP_ECHO_REPLY pong = (PICMP_ECHO_REPLY) replydata;
1230 trace ("send addr : %s\n", ntoa(address));
1231 trace ("reply addr : %s\n", ntoa(pong->Address));
1232 trace ("reply size : %lu\n", replysz);
1233 trace ("roundtrip : %lu ms\n", pong->RoundTripTime);
1234 trace ("status : %lu\n", pong->Status);
1235 trace ("recv size : %u\n", pong->DataSize);
1236 trace ("ttl : %u\n", pong->Options.Ttl);
1237 trace ("flags : 0x%x\n", pong->Options.Flags);
1238 }
1239
1240 /* check reply data */
1241 SetLastError(0xdeadbeef);
1242 address = htonl(INADDR_LOOPBACK);
1243 for (i = 0; i < ARRAY_SIZE(senddata); i++) senddata[i] = i & 0xff;
1244 ret = IcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
1245 error = GetLastError();
1246 reply = (ICMP_ECHO_REPLY *)replydata;
1247 ok(ret, "IcmpSendEcho failed unexpectedly\n");
1248 ok(error == NO_ERROR, "Expect last error:0x%08x, got:0x%08lx\n", NO_ERROR, error);
1249 ok(INADDR_LOOPBACK == ntohl(reply->Address), "Address mismatch, expect:%s, got: %s\n", ntoa(INADDR_LOOPBACK),
1250 ntoa(reply->Address));
1251 ok(reply->Status == IP_SUCCESS, "Expect status:0x%08x, got:0x%08lx\n", IP_SUCCESS, reply->Status);
1252 ok(reply->DataSize == sizeof(senddata), "Got size:%d\n", reply->DataSize);
1253 ok(!memcmp(senddata, reply->Data, min(sizeof(senddata), reply->DataSize)), "Data mismatch\n");
1254
1255
1256 /*
1257 * IcmpSendEcho2
1258 */
1259 address = 0;
1260 replysz = sizeof(replydata2);
1261 memset(senddata, 0, sizeof(senddata));
1262
1263 SetLastError(0xdeadbeef);
1264 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, replysz, 1000);
1265 error = GetLastError();
1266 ok(!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1267 ok(error == ERROR_INVALID_NETNAME
1268 || broken(error == IP_BAD_DESTINATION) /* <= 2003 */,
1269 "expected 1214, got %ld\n", error);
1270
1271 event = CreateEventW(NULL, FALSE, FALSE, NULL);
1272 ok(event != NULL, "CreateEventW failed unexpectedly with error %ld\n", GetLastError());
1273
1274 SetLastError(0xdeadbeef);
1275 ret = IcmpSendEcho2(icmp, event, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, replysz, 1000);
1276 error = GetLastError();
1277 ok(!ret, "IcmpSendEcho2 returned success unexpectedly\n");
1278 ok(error == ERROR_INVALID_NETNAME
1279 || broken(error == ERROR_IO_PENDING) /* <= 2003 */,
1280 "Got last error: 0x%08lx\n", error);
1281 if (error == ERROR_IO_PENDING)
1282 {
1283 ret = WaitForSingleObjectEx(event, 2000, TRUE);
1284 ok(ret == WAIT_OBJECT_0, "WaitForSingleObjectEx failed unexpectedly with %lu\n", ret);
1285 }
1286
1287 address = htonl(INADDR_LOOPBACK);
1288 SetLastError(0xdeadbeef);
1289 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, sizeof(senddata), NULL, NULL, replysz, 1000);
1290 error = GetLastError();
1291 ok(!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1292 ok(error == ERROR_INVALID_PARAMETER
1293 || broken(error == ERROR_NOACCESS) /* <= 2003 */,
1294 "expected 87, got %ld\n", error);
1295
1296 SetLastError(0xdeadbeef);
1297 ret = IcmpSendEcho2(icmp, event, NULL, NULL, address, senddata, sizeof(senddata), NULL, NULL, replysz, 1000);
1298 error = GetLastError();
1299 ok(!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1300 ok(error == ERROR_INVALID_PARAMETER
1301 || broken(error == ERROR_NOACCESS) /* <= 2003 */,
1302 "expected 87, got %ld\n", error);
1303 ok(WaitForSingleObjectEx(event, 0, TRUE) == WAIT_TIMEOUT, "Event was unexpectedly signalled.\n");
1304
1305 SetLastError(0xdeadbeef);
1306 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, 0, 1000);
1307 error = GetLastError();
1308 ok(!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1309 ok(error == ERROR_INVALID_PARAMETER
1310 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1311 "expected 87, got %ld\n", error);
1312
1313 SetLastError(0xdeadbeef);
1314 ret = IcmpSendEcho2(icmp, event, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, 0, 1000);
1315 error = GetLastError();
1316 ok(!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1317 ok(error == ERROR_INVALID_PARAMETER
1318 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1319 "expected 87, got %ld\n", error);
1320 ok(WaitForSingleObjectEx(event, 0, TRUE) == WAIT_TIMEOUT, "Event was unexpectedly signalled.\n");
1321
1322 SetLastError(0xdeadbeef);
1323 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, sizeof(senddata), NULL, NULL, 0, 1000);
1324 error = GetLastError();
1325 ok(!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1326 ok(error == ERROR_INVALID_PARAMETER
1327 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1328 "expected 87, got %ld\n", error);
1329
1330 SetLastError(0xdeadbeef);
1331 ret = IcmpSendEcho2(icmp, event, NULL, NULL, address, senddata, sizeof(senddata), NULL, NULL, 0, 1000);
1332 error = GetLastError();
1333 ok(!ret, "IcmpSendEcho2 succeeded unexpectedly\n");
1334 ok(error == ERROR_INVALID_PARAMETER
1335 || broken(error == ERROR_INSUFFICIENT_BUFFER) /* <= 2003 */,
1336 "expected 87, got %ld\n", error);
1337 ok(WaitForSingleObjectEx(event, 0, TRUE) == WAIT_TIMEOUT, "Event was unexpectedly signalled.\n");
1338
1339 /* synchronous tests */
1340#ifdef __REACTOS__
1341 if (LOBYTE(LOWORD(GetVersion())) >= 6) {
1342#endif
1343 SetLastError(0xdeadbeef);
1344 address = htonl(INADDR_LOOPBACK);
1345 replysz = sizeof(ICMP_ECHO_REPLY) + sizeof(IO_STATUS_BLOCK);
1346 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, 0, NULL, replydata2, replysz, 1000);
1347 ok(ret, "IcmpSendEcho2 failed unexpectedly with error %ld\n", GetLastError());
1348
1349 SetLastError(0xdeadbeef);
1350 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, NULL, 0, NULL, replydata2, replysz, 1000);
1351 ok(ret, "IcmpSendEcho2 failed unexpectedly with error %ld\n", GetLastError());
1352
1353 SetLastError(0xdeadbeef);
1354 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, 0, NULL, replydata2, replysz, 1000);
1355 ok(ret, "IcmpSendEcho2 failed unexpectedly with error %ld\n", GetLastError());
1356
1357 SetLastError(0xdeadbeef);
1358 replysz = sizeof(ICMP_ECHO_REPLY) + sizeof(IO_STATUS_BLOCK) + ICMP_MINLEN;
1359 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, ICMP_MINLEN, NULL, replydata2, replysz, 1000);
1360 ok(ret, "IcmpSendEcho2 failed unexpectedly with error %ld\n", GetLastError());
1361
1362 SetLastError(0xdeadbeef);
1363 replysz = sizeof(replydata2);
1364 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, replysz, 1000);
1365 if (!ret)
1366 {
1367 error = GetLastError();
1368 skip("Failed to ping with error %ld, is lo interface down?\n", error);
1369 }
1370 else if (winetest_debug > 1)
1371 {
1372 reply = (ICMP_ECHO_REPLY*)replydata2;
1373 trace("send addr : %s\n", ntoa(address));
1374 trace("reply addr : %s\n", ntoa(reply->Address));
1375 trace("reply size : %lu\n", replysz);
1376 trace("roundtrip : %lu ms\n", reply->RoundTripTime);
1377 trace("status : %lu\n", reply->Status);
1378 trace("recv size : %u\n", reply->DataSize);
1379 trace("ttl : %u\n", reply->Options.Ttl);
1380 trace("flags : 0x%x\n", reply->Options.Flags);
1381 }
1382
1383 SetLastError(0xdeadbeef);
1384 for (i = 0; i < ARRAY_SIZE(senddata); i++) senddata[i] = i & 0xff;
1385 ret = IcmpSendEcho2(icmp, NULL, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, replysz, 1000);
1386 error = GetLastError();
1387 reply = (ICMP_ECHO_REPLY*)replydata2;
1388 ok(ret, "IcmpSendEcho2 failed unexpectedly\n");
1389 ok(error == NO_ERROR, "Expect last error: 0x%08x, got: 0x%08lx\n", NO_ERROR, error);
1390 ok(ntohl(reply->Address) == INADDR_LOOPBACK, "Address mismatch, expect: %s, got: %s\n", ntoa(INADDR_LOOPBACK),
1391 ntoa(reply->Address));
1392 ok(reply->Status == IP_SUCCESS, "Expect status: 0x%08x, got: 0x%08lx\n", IP_SUCCESS, reply->Status);
1393 ok(reply->DataSize == sizeof(senddata), "Got size: %d\n", reply->DataSize);
1394 ok(!memcmp(senddata, reply->Data, min(sizeof(senddata), reply->DataSize)), "Data mismatch\n");
1395#ifdef __REACTOS__
1396 }
1397#endif
1398
1399 /* asynchronous tests with event */
1400 SetLastError(0xdeadbeef);
1401 replysz = sizeof(replydata2);
1402 address = htonl(INADDR_LOOPBACK);
1403 memset(senddata, 0, sizeof(senddata));
1404 ret = IcmpSendEcho2(icmp, event, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, replysz, 1000);
1405 error = GetLastError();
1406 if (!ret && error != ERROR_IO_PENDING)
1407 {
1408 skip("Failed to ping with error %ld, is lo interface down?\n", error);
1409 }
1410 else
1411 {
1412 ok(!ret, "IcmpSendEcho2 returned success unexpectedly\n");
1413 ok(error == ERROR_IO_PENDING, "Expect last error: 0x%08x, got: 0x%08lx\n", ERROR_IO_PENDING, error);
1414 ret = WaitForSingleObjectEx(event, 2000, TRUE);
1415 ok(ret == WAIT_OBJECT_0, "WaitForSingleObjectEx failed unexpectedly with %lu\n", ret);
1416 reply = (ICMP_ECHO_REPLY*)replydata2;
1417 ok(ntohl(reply->Address) == INADDR_LOOPBACK, "Address mismatch, expect: %s, got: %s\n", ntoa(INADDR_LOOPBACK),
1418 ntoa(reply->Address));
1419#ifdef __REACTOS__
1420 if (LOBYTE(LOWORD(GetVersion())) >= 6) {
1421#endif
1422 ok(reply->Status == IP_SUCCESS, "Expect status: 0x%08x, got: 0x%08lx\n", IP_SUCCESS, reply->Status);
1423 ok(reply->DataSize == sizeof(senddata), "Got size: %d\n", reply->DataSize);
1424#ifdef __REACTOS__
1425 }
1426#endif
1427 if (winetest_debug > 1)
1428 {
1429 reply = (ICMP_ECHO_REPLY*)replydata2;
1430 trace("send addr : %s\n", ntoa(address));
1431 trace("reply addr : %s\n", ntoa(reply->Address));
1432 trace("reply size : %lu\n", replysz);
1433 trace("roundtrip : %lu ms\n", reply->RoundTripTime);
1434 trace("status : %lu\n", reply->Status);
1435 trace("recv size : %u\n", reply->DataSize);
1436 trace("ttl : %u\n", reply->Options.Ttl);
1437 trace("flags : 0x%x\n", reply->Options.Flags);
1438 }
1439 }
1440
1441 SetLastError(0xdeadbeef);
1442 for (i = 0; i < ARRAY_SIZE(senddata); i++) senddata[i] = i & 0xff;
1443 ret = IcmpSendEcho2(icmp, event, NULL, NULL, address, senddata, sizeof(senddata), NULL, replydata2, replysz, 1000);
1444 error = GetLastError();
1445 ok(!ret, "IcmpSendEcho2 returned success unexpectedly\n");
1446 ok(error == ERROR_IO_PENDING, "Expect last error: 0x%08x, got: 0x%08lx\n", ERROR_IO_PENDING, error);
1447 ret = WaitForSingleObjectEx(event, 2000, TRUE);
1448 ok(ret == WAIT_OBJECT_0, "WaitForSingleObjectEx failed unexpectedly with %lu\n", ret);
1449 reply = (ICMP_ECHO_REPLY*)replydata2;
1450 ok(ntohl(reply->Address) == INADDR_LOOPBACK, "Address mismatch, expect: %s, got: %s\n", ntoa(INADDR_LOOPBACK),
1451 ntoa(reply->Address));
1452#ifdef __REACTOS__
1453 if (LOBYTE(LOWORD(GetVersion())) >= 6) {
1454#endif
1455 ok(reply->Status == IP_SUCCESS, "Expect status: 0x%08x, got: 0x%08lx\n", IP_SUCCESS, reply->Status);
1456 ok(reply->DataSize == sizeof(senddata), "Got size: %d\n", reply->DataSize);
1457#ifdef __REACTOS__
1458 }
1459#endif
1460 /* pre-Vista, reply->Data is an offset; otherwise it's a pointer, so hardcode the offset */
1461 ok(!memcmp(senddata, reply + 1, min(sizeof(senddata), reply->DataSize)), "Data mismatch\n");
1462
1463 CloseHandle(event);
1464
1465 /* asynchronous tests with APC */
1466 SetLastError(0xdeadbeef);
1467 replysz = sizeof(replydata2) + 10;
1468 address = htonl(INADDR_LOOPBACK);
1469 for (i = 0; i < ARRAY_SIZE(senddata); i++) senddata[i] = ~i & 0xff;
1470 icmp_send_echo_test_apc_expect = TRUE;
1471 /*
1472 NOTE: Supplying both event and apc has varying behavior across Windows versions, so not tested.
1473 */
1474#if defined(__REACTOS__) && defined(_MSC_VER)
1475 /* The call to IcmpSendEcho2() below with the invalid APC context causes
1476 * stack corruption on WS03 and ReactOS when compiled with MSVC but not GCC. */
1477 if (LOBYTE(LOWORD(GetVersion())) >= 6) {
1478#endif
1479 ret = IcmpSendEcho2(icmp, NULL, apc, (void*)0xdeadc0de, address, senddata, sizeof(senddata), NULL, replydata2, replysz, 1000);
1480 error = GetLastError();
1481 ok(!ret, "IcmpSendEcho2 returned success unexpectedly\n");
1482 ok(error == ERROR_IO_PENDING, "Expect last error: 0x%08x, got: 0x%08lx\n", ERROR_IO_PENDING, error);
1483 SleepEx(200, TRUE);
1484 SleepEx(0, TRUE);
1485 ok(icmp_send_echo_test_apc_expect == FALSE, "APC was not executed!\n");
1486 reply = (ICMP_ECHO_REPLY*)replydata2;
1487 ok(ntohl(reply->Address) == INADDR_LOOPBACK, "Address mismatch, expect: %s, got: %s\n", ntoa(INADDR_LOOPBACK),
1488 ntoa(reply->Address));
1489 ok(reply->Status == IP_SUCCESS, "Expect status: 0x%08x, got: 0x%08lx\n", IP_SUCCESS, reply->Status);
1490 ok(reply->DataSize == sizeof(senddata), "Got size: %d\n", reply->DataSize);
1491 /* pre-Vista, reply->Data is an offset; otherwise it's a pointer, so hardcode the offset */
1492 ok(!memcmp(senddata, reply + 1, min(sizeof(senddata), reply->DataSize)), "Data mismatch\n");
1493#if defined(__REACTOS__) && defined(_MSC_VER)
1494 }
1495#endif
1496
1497 IcmpCloseHandle(icmp);
1498}
1499
1500static void testIcmpParseReplies( void )
1501{
1502 ICMP_ECHO_REPLY reply = { 0 };
1503 DWORD ret;
1504
1505 SetLastError( 0xdeadbeef );
1506 ret = IcmpParseReplies( &reply, sizeof(reply) );
1507 ok( ret == 0, "ret %ld\n", ret );
1508 ok( GetLastError() == 0, "gle %ld\n", GetLastError() );
1509
1510 reply.Status = 12345;
1511 SetLastError( 0xdeadbeef );
1512 ret = IcmpParseReplies( &reply, sizeof(reply) );
1513 ok( ret == 0, "ret %ld\n", ret );
1514 ok( GetLastError() == 12345, "gle %ld\n", GetLastError() );
1515 ok( reply.Status == 12345, "status %ld\n", reply.Status );
1516
1517 reply.Reserved = 1;
1518 SetLastError( 0xdeadbeef );
1519 ret = IcmpParseReplies( &reply, sizeof(reply) );
1520 ok( ret == 1, "ret %ld\n", ret );
1521 ok( GetLastError() == 0xdeadbeef, "gle %ld\n", GetLastError() );
1522 ok( reply.Status == 12345, "status %ld\n", reply.Status );
1523 ok( !reply.Reserved, "reserved %d\n", reply.Reserved );
1524
1525#if defined(__REACTOS__) && defined(_MSC_VER)
1526 /* This crashes on WS03 when compiled with MSVC. It does work on ReactOS. */
1527 if (LOBYTE(LOWORD(GetVersion())) >= 6) {
1528#endif
1529 reply.Reserved = 3;
1530 SetLastError( 0xdeadbeef );
1531 ret = IcmpParseReplies( &reply, sizeof(reply) );
1532 ok( ret == 3, "ret %ld\n", ret );
1533 ok( GetLastError() == 0xdeadbeef, "gle %ld\n", GetLastError() );
1534 ok( reply.Status == 12345, "status %ld\n", reply.Status );
1535 ok( !reply.Reserved, "reserved %d\n", reply.Reserved );
1536#if defined(__REACTOS__) && defined(_MSC_VER)
1537 }
1538#endif
1539}
1540
1541static void testWinNT4Functions(void)
1542{
1543 testGetNumberOfInterfaces();
1544 testGetIpAddrTable();
1545 testGetIfTable();
1546 testGetIpForwardTable();
1547 testGetIpNetTable();
1548 testGetIcmpStatistics();
1549 testGetIpStatistics();
1550 testGetTcpStatistics();
1551 testGetUdpStatistics();
1552 testGetIcmpStatisticsEx();
1553 testGetIpStatisticsEx();
1554 testGetTcpStatisticsEx();
1555 testGetUdpStatisticsEx();
1556 testGetTcpTable();
1557 testGetUdpTable();
1558 testSetTcpEntry();
1559 testIcmpSendEcho();
1560 testIcmpParseReplies();
1561}
1562
1563static void testGetInterfaceInfo(void)
1564{
1565 DWORD apiReturn;
1566 ULONG len = 0, i;
1567
1568 apiReturn = GetInterfaceInfo(NULL, NULL);
1569 if (apiReturn == ERROR_NOT_SUPPORTED) {
1570 skip("GetInterfaceInfo is not supported\n");
1571 return;
1572 }
1573 ok(apiReturn == ERROR_INVALID_PARAMETER,
1574 "GetInterfaceInfo returned %ld, expected ERROR_INVALID_PARAMETER\n",
1575 apiReturn);
1576 apiReturn = GetInterfaceInfo(NULL, &len);
1577 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
1578 "GetInterfaceInfo returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
1579 apiReturn);
1580 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
1581 PIP_INTERFACE_INFO buf = malloc(len);
1582
1583 apiReturn = GetInterfaceInfo(buf, &len);
1584 ok(apiReturn == NO_ERROR,
1585 "GetInterfaceInfo(buf, &dwSize) returned %ld, expected NO_ERROR\n",
1586 apiReturn);
1587
1588 for (i = 0; i < buf->NumAdapters; i++)
1589 {
1590 MIB_IFROW row = { .dwIndex = buf->Adapter[i].Index };
1591 GetIfEntry( &row );
1592#ifdef __REACTOS__
1593 if (LOBYTE(LOWORD(GetVersion())) >= 6) {
1594#endif
1595 ok( !wcscmp( buf->Adapter[i].Name, row.wszName ), "got %s vs %s\n",
1596 debugstr_w( buf->Adapter[i].Name ), debugstr_w( row.wszName ) );
1597#ifdef __REACTOS__
1598 }
1599#endif
1600 ok( row.dwType != IF_TYPE_SOFTWARE_LOOPBACK, "got loopback\n" );
1601 }
1602 free(buf);
1603 }
1604}
1605
1606static void testGetAdaptersInfo(void)
1607{
1608 IP_ADAPTER_INFO *ptr, *buf;
1609 NET_LUID luid;
1610 GUID guid;
1611 char name[ARRAY_SIZE(ptr->AdapterName)];
1612 DWORD err;
1613 ULONG len = 0;
1614 MIB_IFROW row;
1615#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
1616 if(!ConvertInterfaceIndexToLuid || !ConvertInterfaceLuidToGuid) {
1617 skip("Missing APIs!\n");
1618 return;
1619 }
1620#endif
1621
1622 err = GetAdaptersInfo( NULL, NULL );
1623 ok( err == ERROR_INVALID_PARAMETER, "got %ld\n", err );
1624 err = GetAdaptersInfo( NULL, &len );
1625 ok( err == ERROR_NO_DATA || err == ERROR_BUFFER_OVERFLOW, "got %ld\n", err );
1626 if (err == ERROR_NO_DATA) return;
1627
1628 buf = malloc( len );
1629 err = GetAdaptersInfo( buf, &len );
1630 ok( !err, "got %ld\n", err );
1631 ptr = buf;
1632 while (ptr)
1633 {
1634 trace( "adapter '%s', address %s/%s gateway %s/%s\n", ptr->AdapterName,
1635 ptr->IpAddressList.IpAddress.String, ptr->IpAddressList.IpMask.String,
1636 ptr->GatewayList.IpAddress.String, ptr->GatewayList.IpMask.String );
1637 row.dwIndex = ptr->Index;
1638 GetIfEntry( &row );
1639 ConvertInterfaceIndexToLuid( ptr->Index, &luid );
1640 ConvertInterfaceLuidToGuid( &luid, &guid );
1641 sprintf( name, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
1642 guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1],
1643 guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5],
1644 guid.Data4[6], guid.Data4[7] );
1645 ok( !strcmp( ptr->AdapterName, name ), "expected '%s' got '%s'\n", ptr->AdapterName, name );
1646 ok( !strcmp( ptr->Description, (char *)row.bDescr ), "got %s vs %s\n", ptr->Description, (char *)row.bDescr );
1647 ok( ptr->AddressLength == row.dwPhysAddrLen, "got %d vs %ld\n", ptr->AddressLength, row.dwPhysAddrLen );
1648 ok( !memcmp(ptr->Address, row.bPhysAddr, ptr->AddressLength ), "mismatch\n" );
1649 ok( ptr->Type == row.dwType, "got %d vs %ld\n", ptr->Type, row.dwType );
1650 ok( ptr->Type != MIB_IF_TYPE_LOOPBACK, "shouldn't get loopback\n" );
1651 ok( ptr->IpAddressList.IpAddress.String[0], "A valid IP address must be present\n" );
1652 ok( ptr->IpAddressList.IpMask.String[0], "A valid mask must be present\n" );
1653 ok( ptr->GatewayList.IpAddress.String[0], "A valid IP address must be present\n" );
1654 ok( ptr->GatewayList.IpMask.String[0], "A valid mask must be present\n" );
1655 ptr = ptr->Next;
1656 }
1657 free( buf );
1658}
1659
1660static void testGetNetworkParams(void)
1661{
1662 DWORD apiReturn;
1663 ULONG len = 0;
1664
1665 apiReturn = GetNetworkParams(NULL, NULL);
1666 if (apiReturn == ERROR_NOT_SUPPORTED) {
1667 skip("GetNetworkParams is not supported\n");
1668 return;
1669 }
1670 ok(apiReturn == ERROR_INVALID_PARAMETER,
1671 "GetNetworkParams returned %ld, expected ERROR_INVALID_PARAMETER\n",
1672 apiReturn);
1673 apiReturn = GetNetworkParams(NULL, &len);
1674 ok(apiReturn == ERROR_BUFFER_OVERFLOW,
1675 "GetNetworkParams returned %ld, expected ERROR_BUFFER_OVERFLOW\n",
1676 apiReturn);
1677 if (apiReturn == ERROR_BUFFER_OVERFLOW) {
1678 PFIXED_INFO buf = malloc(len);
1679
1680 apiReturn = GetNetworkParams(buf, &len);
1681 ok(apiReturn == NO_ERROR,
1682 "GetNetworkParams(buf, &dwSize) returned %ld, expected NO_ERROR\n",
1683 apiReturn);
1684 free(buf);
1685 }
1686}
1687
1688static void testGetBestInterface(void)
1689{
1690 DWORD apiReturn;
1691 DWORD bestIfIndex;
1692
1693 apiReturn = GetBestInterface( INADDR_ANY, &bestIfIndex );
1694 trace( "GetBestInterface([0.0.0.0], {%lu}) = %lu\n", bestIfIndex, apiReturn );
1695 if (apiReturn == ERROR_NOT_SUPPORTED)
1696 {
1697 skip( "GetBestInterface is not supported\n" );
1698 return;
1699 }
1700
1701 apiReturn = GetBestInterface( INADDR_LOOPBACK, NULL );
1702 ok( apiReturn == ERROR_INVALID_PARAMETER,
1703 "GetBestInterface([127.0.0.1], NULL) returned %lu, expected %d\n",
1704 apiReturn, ERROR_INVALID_PARAMETER );
1705
1706 apiReturn = GetBestInterface( INADDR_LOOPBACK, &bestIfIndex );
1707 ok( apiReturn == NO_ERROR,
1708 "GetBestInterface([127.0.0.1], {%lu}) returned %lu, expected %d\n",
1709 bestIfIndex, apiReturn, NO_ERROR );
1710}
1711
1712static void testGetBestInterfaceEx(void)
1713{
1714 DWORD apiReturn;
1715 DWORD bestIfIndex = 0;
1716 struct sockaddr_in destAddr;
1717
1718 memset(&destAddr, 0, sizeof(struct sockaddr_in));
1719 destAddr.sin_family = AF_INET;
1720 destAddr.sin_addr.S_un.S_addr = INADDR_ANY;
1721 apiReturn = GetBestInterfaceEx( (struct sockaddr *)&destAddr, &bestIfIndex );
1722 trace( "GetBestInterfaceEx([0.0.0.0], {%lu}) = %lu\n", bestIfIndex, apiReturn );
1723 if (apiReturn == ERROR_NOT_SUPPORTED)
1724 {
1725 skip( "GetBestInterfaceEx not supported\n" );
1726 return;
1727 }
1728
1729 apiReturn = GetBestInterfaceEx( NULL, NULL );
1730 ok( apiReturn == ERROR_INVALID_PARAMETER,
1731 "GetBestInterfaceEx(NULL, NULL) returned %lu, expected %d\n",
1732 apiReturn, ERROR_INVALID_PARAMETER );
1733
1734 apiReturn = GetBestInterfaceEx( NULL, &bestIfIndex );
1735 ok( apiReturn == ERROR_INVALID_PARAMETER,
1736 "GetBestInterfaceEx(NULL, {%lu}) returned %lu, expected %d\n",
1737 bestIfIndex, apiReturn, ERROR_INVALID_PARAMETER );
1738
1739 memset(&destAddr, 0, sizeof(struct sockaddr_in));
1740 apiReturn = GetBestInterfaceEx( (struct sockaddr *)&destAddr, NULL );
1741 ok( apiReturn == ERROR_INVALID_PARAMETER,
1742 "GetBestInterfaceEx(<AF_UNSPEC>, NULL) returned %lu, expected %d\n",
1743 apiReturn, ERROR_INVALID_PARAMETER );
1744
1745 memset(&destAddr, -1, sizeof(struct sockaddr_in));
1746 apiReturn = GetBestInterfaceEx( (struct sockaddr *)&destAddr, NULL );
1747 ok( apiReturn == ERROR_INVALID_PARAMETER,
1748 "GetBestInterfaceEx(<INVALID>, NULL) returned %lu, expected %d\n",
1749 apiReturn, ERROR_INVALID_PARAMETER );
1750
1751 memset(&destAddr, 0, sizeof(struct sockaddr_in));
1752 destAddr.sin_family = AF_INET;
1753 destAddr.sin_addr.S_un.S_addr = INADDR_LOOPBACK;
1754 apiReturn = GetBestInterfaceEx( (struct sockaddr *)&destAddr, NULL );
1755 ok( apiReturn == ERROR_INVALID_PARAMETER,
1756 "GetBestInterfaceEx([127.0.0.1], NULL) returned %lu, expected %d\n",
1757 apiReturn, ERROR_INVALID_PARAMETER );
1758
1759 memset(&destAddr, 0, sizeof(struct sockaddr_in));
1760 destAddr.sin_family = AF_INET;
1761 destAddr.sin_addr.S_un.S_addr = INADDR_LOOPBACK;
1762 apiReturn = GetBestInterfaceEx( (struct sockaddr *)&destAddr, &bestIfIndex );
1763 ok( apiReturn == NO_ERROR,
1764 "GetBestInterfaceEx([127.0.0.1], {%lu}) returned %lu, expected %d\n",
1765 bestIfIndex, apiReturn, ERROR_INVALID_PARAMETER );
1766}
1767
1768static void testGetBestRoute(void)
1769{
1770 DWORD apiReturn;
1771 MIB_IPFORWARDROW bestRoute;
1772
1773 apiReturn = GetBestRoute( INADDR_ANY, 0, &bestRoute );
1774 trace( "GetBestRoute([0.0.0.0], 0, [...]) = %lu\n", apiReturn );
1775 if (apiReturn == ERROR_NOT_SUPPORTED)
1776 {
1777 skip( "GetBestRoute is not supported\n" );
1778 return;
1779 }
1780
1781 apiReturn = GetBestRoute( INADDR_ANY, 0, NULL );
1782 ok( apiReturn == ERROR_INVALID_PARAMETER,
1783 "GetBestRoute([0.0.0.0], 0, NULL) returned %lu, expected %d\n",
1784 apiReturn, ERROR_INVALID_PARAMETER );
1785
1786 apiReturn = GetBestRoute( INADDR_LOOPBACK, 0, &bestRoute );
1787 ok( apiReturn == NO_ERROR,
1788 "GetBestRoute([127.0.0.1], 0, NULL) returned %lu, expected %d\n",
1789 apiReturn, NO_ERROR );
1790}
1791
1792/*
1793still-to-be-tested 98-onward functions:
1794IpReleaseAddress
1795IpRenewAddress
1796*/
1797static DWORD CALLBACK testWin98Functions(void *p)
1798{
1799 testGetInterfaceInfo();
1800 testGetAdaptersInfo();
1801 testGetNetworkParams();
1802 testGetBestInterface();
1803 testGetBestInterfaceEx();
1804 testGetBestRoute();
1805 return 0;
1806}
1807
1808static void testGetPerAdapterInfo(void)
1809{
1810 DWORD ret, needed;
1811 void *buffer;
1812
1813 ret = GetPerAdapterInfo(1, NULL, NULL);
1814 ok( ret == ERROR_INVALID_PARAMETER, "got %lu instead of ERROR_INVALID_PARAMETER\n", ret );
1815 needed = 0xdeadbeef;
1816 ret = GetPerAdapterInfo(1, NULL, &needed);
1817 if (ret == ERROR_NO_DATA) return; /* no such adapter */
1818 ok( ret == ERROR_BUFFER_OVERFLOW, "got %lu instead of ERROR_BUFFER_OVERFLOW\n", ret );
1819 ok( needed != 0xdeadbeef, "needed not set\n" );
1820 buffer = malloc( needed );
1821 ret = GetPerAdapterInfo(1, buffer, &needed);
1822 ok( ret == NO_ERROR, "got %lu instead of NO_ERROR\n", ret );
1823 free( buffer );
1824}
1825
1826static void testNotifyAddrChange(void)
1827{
1828 DWORD ret, bytes;
1829 OVERLAPPED overlapped;
1830 HANDLE handle;
1831 BOOL success;
1832
1833#ifdef __REACTOS__
1834 if (IsReactOS()) {
1835 skip("FIXME: testNotifyAddrChange() hangs on ReactOS! (works on Windows)\n");
1836 return;
1837 }
1838#endif
1839 handle = NULL;
1840 ZeroMemory(&overlapped, sizeof(overlapped));
1841 ret = NotifyAddrChange(&handle, &overlapped);
1842 ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %ld, expected ERROR_IO_PENDING\n", ret);
1843 ret = GetLastError();
1844 ok(ret == ERROR_IO_PENDING, "GetLastError returned %ld, expected ERROR_IO_PENDING\n", ret);
1845 success = CancelIPChangeNotify(&overlapped);
1846 ok(success == TRUE, "CancelIPChangeNotify returned FALSE, expected TRUE\n");
1847 success = GetOverlappedResult( handle, &overlapped, &bytes, TRUE );
1848 ok( !success && GetLastError() == ERROR_OPERATION_ABORTED, "got bret %d, err %lu.\n", success, GetLastError() );
1849
1850 ZeroMemory(&overlapped, sizeof(overlapped));
1851 success = CancelIPChangeNotify(&overlapped);
1852 ok(success == FALSE, "CancelIPChangeNotify returned TRUE, expected FALSE\n");
1853
1854 handle = NULL;
1855 ZeroMemory(&overlapped, sizeof(overlapped));
1856 overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1857 ret = NotifyAddrChange(&handle, &overlapped);
1858 ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %ld, expected ERROR_IO_PENDING\n", ret);
1859 ok(handle != INVALID_HANDLE_VALUE, "NotifyAddrChange returned invalid file handle\n");
1860 success = GetOverlappedResult(handle, &overlapped, &bytes, FALSE);
1861 ok(success == FALSE, "GetOverlappedResult returned TRUE, expected FALSE\n");
1862 ret = GetLastError();
1863 ok(ret == ERROR_IO_INCOMPLETE, "GetLastError returned %ld, expected ERROR_IO_INCOMPLETE\n", ret);
1864 success = CancelIPChangeNotify(&overlapped);
1865 ok(success == TRUE, "CancelIPChangeNotify returned FALSE, expected TRUE\n");
1866 success = GetOverlappedResult( handle, &overlapped, &bytes, TRUE );
1867 ok( !success && GetLastError() == ERROR_OPERATION_ABORTED, "got bret %d, err %lu.\n", success, GetLastError() );
1868
1869 if (winetest_interactive)
1870 {
1871 handle = NULL;
1872 ZeroMemory(&overlapped, sizeof(overlapped));
1873 overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1874 trace("Testing asynchronous ipv4 address change notification. Please "
1875 "change the ipv4 address of one of your network interfaces\n");
1876 ret = NotifyAddrChange(&handle, &overlapped);
1877 ok(ret == ERROR_IO_PENDING, "NotifyAddrChange returned %ld, expected NO_ERROR\n", ret);
1878 success = GetOverlappedResult(handle, &overlapped, &bytes, TRUE);
1879 ok(success == TRUE, "GetOverlappedResult returned FALSE, expected TRUE\n");
1880 }
1881
1882 /* test synchronous functionality */
1883 if (winetest_interactive)
1884 {
1885 trace("Testing synchronous ipv4 address change notification. Please "
1886 "change the ipv4 address of one of your network interfaces\n");
1887 ret = NotifyAddrChange(NULL, NULL);
1888 ok(ret == NO_ERROR, "NotifyAddrChange returned %ld, expected NO_ERROR\n", ret);
1889 }
1890}
1891
1892/*
1893still-to-be-tested 2K-onward functions:
1894AddIPAddress
1895CreateProxyArpEntry
1896DeleteIPAddress
1897DeleteProxyArpEntry
1898EnableRouter
1899FlushIpNetTable
1900GetAdapterIndex
1901NotifyRouteChange + CancelIPChangeNotify
1902SendARP
1903UnenableRouter
1904*/
1905static void testWin2KFunctions(void)
1906{
1907 testGetPerAdapterInfo();
1908 testNotifyAddrChange();
1909}
1910
1911static void test_GetAdaptersAddresses(void)
1912{
1913 BOOL dns_eligible_found = FALSE;
1914 ULONG ret, size, osize, i;
1915 IP_ADAPTER_ADDRESSES *aa, *ptr;
1916 IP_ADAPTER_UNICAST_ADDRESS *ua;
1917
1918#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
1919 if (!ConvertInterfaceLuidToGuid)
1920 skip("Missing APIs!\n");
1921#endif
1922 ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, NULL);
1923 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %lu\n", ret);
1924
1925 /* size should be ignored and overwritten if buffer is NULL */
1926 size = 0x7fffffff;
1927 ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
1928 ok(ret == ERROR_BUFFER_OVERFLOW, "expected ERROR_BUFFER_OVERFLOW, got %lu\n", ret);
1929 if (ret != ERROR_BUFFER_OVERFLOW) return;
1930
1931 /* GAA_FLAG_SKIP_FRIENDLY_NAME is ignored */
1932 osize = 0x7fffffff;
1933 ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, NULL, &osize);
1934 ok(ret == ERROR_BUFFER_OVERFLOW, "expected ERROR_BUFFER_OVERFLOW, got %lu\n", ret);
1935#ifdef __REACTOS__
1936 if (LOBYTE(LOWORD(GetVersion())) >= 6)
1937#endif
1938 ok(osize == size, "expected %ld, got %ld\n", size, osize);
1939
1940 ptr = malloc(size);
1941 ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, ptr, &size);
1942 ok(!ret, "expected ERROR_SUCCESS got %lu\n", ret);
1943 free(ptr);
1944
1945 /* higher size must not be changed to lower size */
1946 size *= 2;
1947 osize = size;
1948 ptr = malloc(osize);
1949 ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, ptr, &osize);
1950 while (ret == ERROR_BUFFER_OVERFLOW)
1951 {
1952 size = osize * 2;
1953 osize = size;
1954 ptr = realloc(ptr, osize);
1955 ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, ptr, &osize);
1956 }
1957 ok(!ret, "expected ERROR_SUCCESS got %lu\n", ret);
1958 ok(osize == size, "expected %ld, got %ld\n", size, osize);
1959
1960 for (aa = ptr; !ret && aa; aa = aa->Next)
1961 {
1962 char temp[128], buf[39];
1963 IP_ADAPTER_PREFIX *prefix;
1964 DWORD status;
1965 GUID guid;
1966
1967 ok(aa->Length == sizeof(IP_ADAPTER_ADDRESSES_LH) ||
1968 aa->Length == sizeof(IP_ADAPTER_ADDRESSES_XP),
1969 "Unknown structure size of %lu bytes\n", aa->Length);
1970 ok(aa->DnsSuffix != NULL, "DnsSuffix is not a valid pointer\n");
1971 ok(aa->Description != NULL, "Description is not a valid pointer\n");
1972 ok(aa->FriendlyName != NULL, "FriendlyName is not a valid pointer\n");
1973
1974 for (i = 0; i < aa->PhysicalAddressLength; i++)
1975 sprintf(temp + i * 3, "%02X-", aa->PhysicalAddress[i]);
1976 temp[i ? i * 3 - 1 : 0] = '\0';
1977 trace("idx %lu name %s %s dns %s descr %s phys %s mtu %lu flags %08lx type %lu\n",
1978 aa->IfIndex, aa->AdapterName,
1979 wine_dbgstr_w(aa->FriendlyName), wine_dbgstr_w(aa->DnsSuffix),
1980 wine_dbgstr_w(aa->Description), temp, aa->Mtu, aa->Flags, aa->IfType );
1981 ua = aa->FirstUnicastAddress;
1982 while (ua)
1983 {
1984 ok(ua->Length == sizeof(IP_ADAPTER_UNICAST_ADDRESS_LH) ||
1985 ua->Length == sizeof(IP_ADAPTER_UNICAST_ADDRESS_XP),
1986 "Unknown structure size of %lu bytes\n", ua->Length);
1987 ok(ua->PrefixOrigin != IpPrefixOriginOther,
1988 "bad address config value %d\n", ua->PrefixOrigin);
1989 ok(ua->SuffixOrigin != IpSuffixOriginOther,
1990 "bad address config value %d\n", ua->PrefixOrigin);
1991 /* Address configured manually or from DHCP server? */
1992 if (ua->PrefixOrigin == IpPrefixOriginManual ||
1993 ua->PrefixOrigin == IpPrefixOriginDhcp)
1994 {
1995 ok(ua->ValidLifetime, "expected non-zero value\n");
1996 ok(ua->PreferredLifetime, "expected non-zero value\n");
1997 ok(ua->LeaseLifetime, "expected non-zero\n");
1998 }
1999 /* Is the address ok in the network (not duplicated)? */
2000 ok(ua->DadState != IpDadStateInvalid && ua->DadState != IpDadStateDuplicate,
2001 "bad address duplication value %d\n", ua->DadState);
2002 trace(" flags %08lx origin %u/%u state %u lifetime %lu/%lu/%lu prefix %u\n",
2003 ua->Flags, ua->PrefixOrigin, ua->SuffixOrigin, ua->DadState,
2004 ua->ValidLifetime, ua->PreferredLifetime, ua->LeaseLifetime,
2005 ua->Length < sizeof(IP_ADAPTER_UNICAST_ADDRESS_LH) ? 0 : ua->OnLinkPrefixLength);
2006
2007 if (ua->Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE)
2008 dns_eligible_found = TRUE;
2009
2010#ifdef __REACTOS__
2011 if (LOBYTE(LOWORD(GetVersion())) >= 6) {
2012#endif
2013 if(ua->Address.lpSockaddr->sa_family == AF_INET)
2014 ok(aa->Ipv4Enabled == TRUE, "expected Ipv4Enabled flag to be set in interface %ls\n", aa->FriendlyName);
2015 else if(ua->Address.lpSockaddr->sa_family == AF_INET6)
2016 ok(aa->Ipv6Enabled == TRUE, "expected Ipv6Enabled flag to be set in interface %ls\n", aa->FriendlyName);
2017#ifdef __REACTOS__
2018 }
2019#endif
2020
2021 ua = ua->Next;
2022 }
2023 for (i = 0, temp[0] = '\0'; i < ARRAY_SIZE(aa->ZoneIndices); i++)
2024 sprintf(temp + strlen(temp), "%ld ", aa->ZoneIndices[i]);
2025 trace("status %u index %lu zone %s\n", aa->OperStatus, aa->Ipv6IfIndex, temp );
2026 prefix = aa->FirstPrefix;
2027 while (prefix)
2028 {
2029 trace( " prefix %u/%lu flags %08lx\n", prefix->Address.iSockaddrLength,
2030 prefix->PrefixLength, prefix->Flags );
2031 prefix = prefix->Next;
2032 }
2033
2034 if (aa->Length < sizeof(IP_ADAPTER_ADDRESSES_LH)) continue;
2035 trace("speed %s/%s metrics %lu/%lu guid %s type %u/%u\n",
2036 wine_dbgstr_longlong(aa->TransmitLinkSpeed),
2037 wine_dbgstr_longlong(aa->ReceiveLinkSpeed),
2038 aa->Ipv4Metric, aa->Ipv6Metric, wine_dbgstr_guid((GUID*) &aa->NetworkGuid),
2039 aa->ConnectionType, aa->TunnelType);
2040
2041#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
2042 if (ConvertInterfaceLuidToGuid) {
2043#endif
2044 status = ConvertInterfaceLuidToGuid(&aa->Luid, &guid);
2045 ok(!status, "got %lu\n", status);
2046 sprintf(buf, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
2047 guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1],
2048 guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5],
2049 guid.Data4[6], guid.Data4[7]);
2050 ok(!strcasecmp(aa->AdapterName, buf), "expected '%s' got '%s'\n", aa->AdapterName, buf);
2051#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
2052 }
2053#endif
2054 }
2055 ok(dns_eligible_found, "Did not find any dns eligible addresses.\n");
2056 free(ptr);
2057}
2058
2059static DWORD get_extended_tcp_table( ULONG family, TCP_TABLE_CLASS class, void **table )
2060{
2061 DWORD ret, size = 0;
2062
2063 *table = NULL;
2064 ret = pGetExtendedTcpTable( NULL, &size, TRUE, family, class, 0 );
2065 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
2066
2067 *table = malloc( size );
2068 ret = pGetExtendedTcpTable( *table, &size, TRUE, family, class, 0 );
2069 while (ret == ERROR_INSUFFICIENT_BUFFER)
2070 {
2071 *table = realloc( *table, size );
2072 ret = pGetExtendedTcpTable( *table, &size, TRUE, family, class, 0 );
2073 }
2074 return ret;
2075}
2076
2077static void test_GetExtendedTcpTable(void)
2078{
2079 DWORD ret;
2080 MIB_TCPTABLE *table;
2081 MIB_TCPTABLE_OWNER_PID *table_pid;
2082 MIB_TCPTABLE_OWNER_MODULE *table_module;
2083
2084 if (!pGetExtendedTcpTable)
2085 {
2086 win_skip("GetExtendedTcpTable not available\n");
2087 return;
2088 }
2089 ret = pGetExtendedTcpTable( NULL, NULL, TRUE, AF_INET, TCP_TABLE_BASIC_ALL, 0 );
2090 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2091
2092 ret = get_extended_tcp_table( AF_INET, TCP_TABLE_BASIC_ALL, (void **)&table );
2093 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2094 free( table );
2095
2096 ret = get_extended_tcp_table( AF_INET, TCP_TABLE_BASIC_LISTENER, (void **)&table );
2097 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2098 free( table );
2099
2100 ret = get_extended_tcp_table( AF_INET, TCP_TABLE_OWNER_PID_ALL, (void **)&table_pid );
2101 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2102 free( table_pid );
2103
2104 ret = get_extended_tcp_table( AF_INET, TCP_TABLE_OWNER_PID_LISTENER, (void **)&table_pid );
2105 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2106 free( table_pid );
2107
2108 ret = get_extended_tcp_table( AF_INET, TCP_TABLE_OWNER_MODULE_ALL, (void **)&table_module );
2109 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2110 free( table_module );
2111
2112 ret = get_extended_tcp_table( AF_INET, TCP_TABLE_OWNER_MODULE_LISTENER, (void **)&table_module );
2113 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2114 free( table_module );
2115}
2116
2117/* Test that the TCP_TABLE_OWNER_PID_ALL table contains an entry for a socket
2118 we make, and associates it with our process. */
2119static void test_GetExtendedTcpTable_owner( int family )
2120{
2121 SOCKET sock;
2122 int port;
2123 DWORD i, ret;
2124 void *raw_table = NULL;
2125
2126#ifdef __REACTOS__
2127 if (LOBYTE(LOWORD(GetVersion())) < 6) {
2128 skip("This test is invalid for this NT version.\n");
2129 return;
2130 }
2131#endif
2132 winetest_push_context( "%s", family == AF_INET ? "AF_INET" : "AF_INET6" );
2133
2134 sock = socket( family, SOCK_STREAM, IPPROTO_TCP );
2135 ok( sock != INVALID_SOCKET, "socket error %d\n", WSAGetLastError() );
2136
2137 if (family == AF_INET)
2138 {
2139 struct sockaddr_in addr = { 0 };
2140 int addr_len = sizeof(addr);
2141
2142 addr.sin_family = AF_INET;
2143 addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2144 addr.sin_port = 0;
2145
2146 ret = bind( sock, (struct sockaddr *)&addr, addr_len );
2147 ok( !ret, "bind error %d\n", WSAGetLastError() );
2148 ret = getsockname( sock, (struct sockaddr *)&addr, &addr_len );
2149 ok( !ret, "getsockname error %d\n", WSAGetLastError() );
2150
2151 port = addr.sin_port;
2152 }
2153 else
2154 {
2155 struct sockaddr_in6 addr = { 0 };
2156 int addr_len = sizeof(addr);
2157
2158 addr.sin6_family = AF_INET6;
2159 addr.sin6_addr = in6addr_loopback;
2160 addr.sin6_port = 0;
2161
2162 ret = bind( sock, (struct sockaddr *)&addr, addr_len );
2163 ok( !ret, "bind error %d\n", WSAGetLastError() );
2164 ret = getsockname( sock, (struct sockaddr *)&addr, &addr_len );
2165 ok( !ret, "getsockname error %d\n", WSAGetLastError() );
2166
2167 port = addr.sin6_port;
2168 }
2169
2170 listen( sock, 1 );
2171
2172 ret = get_extended_tcp_table( family, TCP_TABLE_OWNER_PID_ALL, &raw_table );
2173 if (ret != ERROR_SUCCESS)
2174 {
2175 skip( "error %lu getting TCP table\n", ret );
2176 goto done;
2177 }
2178
2179 if (family == AF_INET)
2180 {
2181 MIB_TCPTABLE_OWNER_PID *table = raw_table;
2182 BOOL found_it = FALSE;
2183 for (i = 0; i < table->dwNumEntries; i++)
2184 {
2185 MIB_TCPROW_OWNER_PID *row = &table->table[i];
2186 if (row->dwLocalPort == port && row->dwLocalAddr == htonl( INADDR_LOOPBACK ))
2187 {
2188 ok( row->dwState == MIB_TCP_STATE_LISTEN, "unexpected socket state %ld\n", row->dwState );
2189 ok( row->dwOwningPid == GetCurrentProcessId(), "unexpected socket owner %04lx\n", row->dwOwningPid );
2190 found_it = TRUE;
2191 break;
2192 }
2193 }
2194 ok( found_it, "no table entry for socket\n" );
2195 }
2196 else
2197 {
2198 MIB_TCP6TABLE_OWNER_PID *table = raw_table;
2199 BOOL found_it = FALSE;
2200 for (i = 0; i < table->dwNumEntries; i++)
2201 {
2202 MIB_TCP6ROW_OWNER_PID *row = &table->table[i];
2203 if (row->dwLocalPort == port && IN6_IS_ADDR_LOOPBACK( (IN6_ADDR*)&row->ucLocalAddr ))
2204 {
2205 ok( row->dwState == MIB_TCP_STATE_LISTEN, "unexpected socket state %ld\n", row->dwState );
2206 ok( row->dwOwningPid == GetCurrentProcessId(), "unexpected socket owner %04lx\n", row->dwOwningPid );
2207 found_it = TRUE;
2208 break;
2209 }
2210 }
2211 ok( found_it, "no table entry for socket\n" );
2212 }
2213
2214done:
2215 closesocket( sock );
2216 free( raw_table );
2217
2218 winetest_pop_context();
2219}
2220
2221static void test_AllocateAndGetTcpExTableFromStack(void)
2222{
2223 DWORD ret;
2224 MIB_TCPTABLE_OWNER_PID *table_ex = NULL;
2225
2226 if (!pAllocateAndGetTcpExTableFromStack)
2227 {
2228 win_skip("AllocateAndGetTcpExTableFromStack not available\n");
2229 return;
2230 }
2231
2232 if (0)
2233 {
2234 /* crashes on native */
2235 ret = pAllocateAndGetTcpExTableFromStack( NULL, FALSE, INVALID_HANDLE_VALUE, 0, 0 );
2236 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2237 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, INVALID_HANDLE_VALUE, 0, AF_INET );
2238 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2239 ret = pAllocateAndGetTcpExTableFromStack( NULL, FALSE, GetProcessHeap(), 0, AF_INET );
2240 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2241 }
2242
2243 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, GetProcessHeap(), 0, 0 );
2244 ok( ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_NOT_SUPPORTED) /* win2k */, "got %lu\n", ret );
2245
2246 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, GetProcessHeap(), 0, AF_INET );
2247 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2248
2249 if (ret == NO_ERROR && winetest_debug > 1)
2250 {
2251 DWORD i;
2252 trace( "AllocateAndGetTcpExTableFromStack table: %lu entries\n", table_ex->dwNumEntries );
2253 for (i = 0; i < table_ex->dwNumEntries; i++)
2254 {
2255 char remote_ip[16];
2256
2257 strcpy(remote_ip, ntoa(table_ex->table[i].dwRemoteAddr));
2258 trace( "%lu: local %s:%u remote %s:%u state %lu pid %lu\n", i,
2259 ntoa(table_ex->table[i].dwLocalAddr), ntohs(table_ex->table[i].dwLocalPort),
2260 remote_ip, ntohs(table_ex->table[i].dwRemotePort),
2261 table_ex->table[i].dwState, table_ex->table[i].dwOwningPid );
2262 }
2263 }
2264 HeapFree(GetProcessHeap(), 0, table_ex);
2265
2266 ret = pAllocateAndGetTcpExTableFromStack( (void **)&table_ex, FALSE, GetProcessHeap(), 0, AF_INET6 );
2267 ok( ret == ERROR_NOT_SUPPORTED, "got %lu\n", ret );
2268}
2269
2270static DWORD get_extended_udp_table( ULONG family, UDP_TABLE_CLASS class, void **table )
2271{
2272 DWORD ret, size = 0;
2273
2274 *table = NULL;
2275 ret = pGetExtendedUdpTable( NULL, &size, TRUE, family, class, 0 );
2276 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
2277
2278 *table = malloc( size );
2279 ret = pGetExtendedUdpTable( *table, &size, TRUE, family, class, 0 );
2280 while (ret == ERROR_INSUFFICIENT_BUFFER)
2281 {
2282 *table = realloc( *table, size );
2283 ret = pGetExtendedUdpTable( *table, &size, TRUE, family, class, 0 );
2284 }
2285 return ret;
2286}
2287
2288static void test_GetExtendedUdpTable(void)
2289{
2290 DWORD ret;
2291 MIB_UDPTABLE *table;
2292 MIB_UDPTABLE_OWNER_PID *table_pid;
2293 MIB_UDPTABLE_OWNER_MODULE *table_module;
2294
2295 if (!pGetExtendedUdpTable)
2296 {
2297 win_skip("GetExtendedUdpTable not available\n");
2298 return;
2299 }
2300 ret = pGetExtendedUdpTable( NULL, NULL, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
2301 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2302
2303 ret = get_extended_udp_table( AF_INET, UDP_TABLE_BASIC, (void **)&table );
2304 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2305 free( table );
2306
2307 ret = get_extended_udp_table( AF_INET, UDP_TABLE_OWNER_PID, (void **)&table_pid );
2308 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2309 free( table_pid );
2310
2311 ret = get_extended_udp_table( AF_INET, UDP_TABLE_OWNER_MODULE, (void **)&table_module );
2312 ok( ret == ERROR_SUCCESS, "got %lu\n", ret );
2313 free( table_module );
2314}
2315
2316/* Test that the UDP_TABLE_OWNER_PID table contains an entry for a socket we
2317 make, and associates it with our process. */
2318static void test_GetExtendedUdpTable_owner( int family )
2319{
2320 SOCKET sock;
2321 int port;
2322 DWORD i, ret;
2323 void *raw_table = NULL;
2324
2325#ifdef __REACTOS__
2326 if (LOBYTE(LOWORD(GetVersion())) < 6) {
2327 skip("This test is invalid for this NT version.\n");
2328 return;
2329 }
2330#endif
2331 winetest_push_context( "%s", family == AF_INET ? "AF_INET" : "AF_INET6" );
2332
2333 sock = socket( family, SOCK_DGRAM, IPPROTO_UDP );
2334 ok( sock != INVALID_SOCKET, "socket error %d\n", WSAGetLastError() );
2335
2336 if (family == AF_INET)
2337 {
2338 struct sockaddr_in addr = { 0 };
2339 int addr_len = sizeof(addr);
2340
2341 addr.sin_family = AF_INET;
2342 addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2343 addr.sin_port = 0;
2344
2345 ret = bind( sock, (struct sockaddr *)&addr, addr_len );
2346 ok( !ret, "bind error %d\n", WSAGetLastError() );
2347 ret = getsockname( sock, (struct sockaddr *)&addr, &addr_len );
2348 ok( !ret, "getsockname error %d\n", WSAGetLastError() );
2349
2350 port = addr.sin_port;
2351 }
2352 else
2353 {
2354 struct sockaddr_in6 addr = { 0 };
2355 int addr_len = sizeof(addr);
2356
2357 addr.sin6_family = AF_INET6;
2358 addr.sin6_addr = in6addr_loopback;
2359 addr.sin6_port = 0;
2360
2361 ret = bind( sock, (struct sockaddr *)&addr, addr_len );
2362 ok( !ret, "bind error %d\n", WSAGetLastError() );
2363 ret = getsockname( sock, (struct sockaddr *)&addr, &addr_len );
2364 ok( !ret, "getsockname error %d\n", WSAGetLastError() );
2365
2366 port = addr.sin6_port;
2367 }
2368
2369 ret = get_extended_udp_table( family, UDP_TABLE_OWNER_PID, &raw_table );
2370 if (ret != ERROR_SUCCESS)
2371 {
2372 skip( "error %lu getting UDP table\n", ret );
2373 goto done;
2374 }
2375
2376 if (family == AF_INET)
2377 {
2378 MIB_UDPTABLE_OWNER_PID *table = raw_table;
2379 BOOL found_it = FALSE;
2380 for (i = 0; i < table->dwNumEntries; i++)
2381 {
2382 MIB_UDPROW_OWNER_PID *row = &table->table[i];
2383 if (row->dwLocalPort == port && row->dwLocalAddr == htonl( INADDR_LOOPBACK ))
2384 {
2385 ok( row->dwOwningPid == GetCurrentProcessId(), "unexpected socket owner %04lx\n", row->dwOwningPid );
2386 found_it = TRUE;
2387 break;
2388 }
2389 }
2390 ok( found_it, "no table entry for socket\n" );
2391 }
2392 else
2393 {
2394 MIB_UDP6TABLE_OWNER_PID *table = raw_table;
2395 BOOL found_it = FALSE;
2396 for (i = 0; i < table->dwNumEntries; i++)
2397 {
2398 MIB_UDP6ROW_OWNER_PID *row = &table->table[i];
2399 if (row->dwLocalPort == port && IN6_IS_ADDR_LOOPBACK( (IN6_ADDR*)&row->ucLocalAddr ))
2400 {
2401 ok( row->dwOwningPid == GetCurrentProcessId(), "unexpected socket owner %04lx\n", row->dwOwningPid );
2402 found_it = TRUE;
2403 break;
2404 }
2405 }
2406 ok( found_it, "no table entry for socket\n" );
2407 }
2408
2409done:
2410 closesocket( sock );
2411 free( raw_table );
2412
2413 winetest_pop_context();
2414}
2415
2416static void test_CreateSortedAddressPairs(void)
2417{
2418 SOCKADDR_IN6 dst[2];
2419 SOCKADDR_IN6_PAIR *pair;
2420 ULONG pair_count;
2421 DWORD ret;
2422
2423 if (!pCreateSortedAddressPairs)
2424 {
2425 win_skip( "CreateSortedAddressPairs not available\n" );
2426 return;
2427 }
2428
2429 memset( dst, 0, sizeof(dst) );
2430 dst[0].sin6_family = AF_INET6;
2431 dst[0].sin6_addr.u.Word[5] = 0xffff;
2432 dst[0].sin6_addr.u.Word[6] = 0x0808;
2433 dst[0].sin6_addr.u.Word[7] = 0x0808;
2434
2435 pair_count = 0xdeadbeef;
2436 ret = pCreateSortedAddressPairs( NULL, 0, dst, 1, 0, NULL, &pair_count );
2437 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2438 ok( pair_count == 0xdeadbeef, "got %lu\n", pair_count );
2439
2440 pair = (SOCKADDR_IN6_PAIR *)0xdeadbeef;
2441 pair_count = 0xdeadbeef;
2442 ret = pCreateSortedAddressPairs( NULL, 0, NULL, 1, 0, &pair, &pair_count );
2443 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2444 ok( pair == (SOCKADDR_IN6_PAIR *)0xdeadbeef, "got %p\n", pair );
2445 ok( pair_count == 0xdeadbeef, "got %lu\n", pair_count );
2446
2447 pair = NULL;
2448 pair_count = 0xdeadbeef;
2449 ret = pCreateSortedAddressPairs( NULL, 0, dst, 1, 0, &pair, &pair_count );
2450 ok( ret == NO_ERROR, "got %lu\n", ret );
2451 ok( pair != NULL, "pair not set\n" );
2452 ok( pair_count >= 1, "got %lu\n", pair_count );
2453 ok( pair[0].SourceAddress != NULL, "src address not set\n" );
2454 ok( pair[0].DestinationAddress != NULL, "dst address not set\n" );
2455 FreeMibTable( pair );
2456
2457 dst[1].sin6_family = AF_INET6;
2458 dst[1].sin6_addr.u.Word[5] = 0xffff;
2459 dst[1].sin6_addr.u.Word[6] = 0x0404;
2460 dst[1].sin6_addr.u.Word[7] = 0x0808;
2461
2462 pair = NULL;
2463 pair_count = 0xdeadbeef;
2464 ret = pCreateSortedAddressPairs( NULL, 0, dst, 2, 0, &pair, &pair_count );
2465 ok( ret == NO_ERROR, "got %lu\n", ret );
2466 ok( pair != NULL, "pair not set\n" );
2467 ok( pair_count >= 2, "got %lu\n", pair_count );
2468 ok( pair[0].SourceAddress != NULL, "src address not set\n" );
2469 ok( pair[0].DestinationAddress != NULL, "dst address not set\n" );
2470 ok( pair[1].SourceAddress != NULL, "src address not set\n" );
2471 ok( pair[1].DestinationAddress != NULL, "dst address not set\n" );
2472 FreeMibTable( pair );
2473}
2474
2475static IP_ADAPTER_ADDRESSES *get_adapters( ULONG flags )
2476{
2477 ULONG err, size = 4096;
2478 IP_ADAPTER_ADDRESSES *tmp, *ret;
2479
2480 if (!(ret = malloc( size ))) return NULL;
2481 err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
2482 while (err == ERROR_BUFFER_OVERFLOW)
2483 {
2484 if (!(tmp = realloc( ret, size ))) break;
2485 ret = tmp;
2486 err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
2487 }
2488 if (err == ERROR_SUCCESS) return ret;
2489 free( ret );
2490 return NULL;
2491}
2492
2493static DWORD get_interface_index(void)
2494{
2495 DWORD ret = 0;
2496 IP_ADAPTER_ADDRESSES *buf, *aa;
2497
2498 buf = get_adapters( 0 );
2499 if (!buf) return 0;
2500
2501 for (aa = buf; aa; aa = aa->Next)
2502 {
2503 if (aa->IfType == IF_TYPE_ETHERNET_CSMACD)
2504 {
2505 ret = aa->IfIndex;
2506 break;
2507 }
2508 }
2509 free( buf );
2510 return ret;
2511}
2512
2513static void convert_luid_to_name( NET_LUID *luid, WCHAR *expect_nameW, int len )
2514{
2515 struct
2516 {
2517 const WCHAR *prefix;
2518 DWORD type;
2519 } prefixes[] =
2520 {
2521 { L"other", IF_TYPE_OTHER },
2522 { L"ethernet", IF_TYPE_ETHERNET_CSMACD },
2523 { L"tokenring", IF_TYPE_ISO88025_TOKENRING },
2524 { L"ppp", IF_TYPE_PPP },
2525 { L"loopback", IF_TYPE_SOFTWARE_LOOPBACK },
2526 { L"atm", IF_TYPE_ATM },
2527 { L"wireless", IF_TYPE_IEEE80211 },
2528 { L"tunnel", IF_TYPE_TUNNEL },
2529 { L"ieee1394", IF_TYPE_IEEE1394 }
2530 };
2531 DWORD i;
2532 const WCHAR *prefix = NULL;
2533
2534 for (i = 0; i < ARRAY_SIZE(prefixes); i++)
2535 {
2536 if (prefixes[i].type == luid->Info.IfType)
2537 {
2538 prefix = prefixes[i].prefix;
2539 break;
2540 }
2541 }
2542#ifdef __REACTOS__
2543 if (prefix)
2544 _snwprintf( expect_nameW, len, L"%s_%d", prefix, luid->Info.NetLuidIndex );
2545 else
2546 _snwprintf( expect_nameW, len, L"iftype%d_%d", luid->Info.IfType, luid->Info.NetLuidIndex );
2547#else
2548 if (prefix)
2549 swprintf( expect_nameW, len, L"%s_%d", prefix, luid->Info.NetLuidIndex );
2550 else
2551 swprintf( expect_nameW, len, L"iftype%d_%d", luid->Info.IfType, luid->Info.NetLuidIndex );
2552#endif
2553}
2554
2555static void test_interface_identifier_conversion(void)
2556{
2557 DWORD ret, i;
2558 NET_LUID luid;
2559 GUID guid;
2560 SIZE_T len;
2561 WCHAR nameW[IF_MAX_STRING_SIZE + 1];
2562 WCHAR alias[IF_MAX_STRING_SIZE + 1];
2563 WCHAR expect_nameW[IF_MAX_STRING_SIZE + 1];
2564 char nameA[IF_MAX_STRING_SIZE + 1], *name;
2565 char expect_nameA[IF_MAX_STRING_SIZE + 1];
2566 NET_IFINDEX index;
2567 MIB_IF_TABLE2 *table;
2568
2569#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
2570 if (!ConvertInterfaceIndexToLuid || !ConvertInterfaceLuidToIndex ||
2571 !ConvertInterfaceLuidToGuid || !ConvertInterfaceGuidToLuid ||
2572 !ConvertInterfaceLuidToNameW || !ConvertInterfaceLuidToNameA ||
2573 !ConvertInterfaceNameToLuidW || !ConvertInterfaceNameToLuidA ||
2574 !pConvertInterfaceAliasToLuid || !pConvertInterfaceLuidToAlias ||
2575 !GetIfTable2 || !if_nametoindex || !if_indextoname) {
2576 skip("Missing APIs!\n");
2577 return;
2578 }
2579#endif
2580 ret = GetIfTable2( &table );
2581 ok( !ret, "got %ld\n", ret );
2582
2583 for (i = 0; i < table->NumEntries; i++)
2584 {
2585 MIB_IF_ROW2 *row = table->Table + i;
2586
2587 /* ConvertInterfaceIndexToLuid */
2588 memset( &luid, 0xff, sizeof(luid) );
2589 ret = ConvertInterfaceIndexToLuid( 0, &luid );
2590 ok( ret == ERROR_FILE_NOT_FOUND, "got %lu\n", ret );
2591 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
2592 ok( !luid.Info.NetLuidIndex, "got %u\n", luid.Info.NetLuidIndex );
2593 ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType );
2594
2595 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
2596 ret = ConvertInterfaceIndexToLuid( row->InterfaceIndex, &luid );
2597 ok( !ret, "got %lu\n", ret );
2598 ok( luid.Value == row->InterfaceLuid.Value, "mismatch\n" );
2599
2600 /* ConvertInterfaceLuidToIndex */
2601 ret = ConvertInterfaceLuidToIndex( &luid, NULL );
2602 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2603
2604 ret = ConvertInterfaceLuidToIndex( &luid, &index );
2605 ok( !ret, "got %lu\n", ret );
2606 ok( index == row->InterfaceIndex, "mismatch\n" );
2607
2608 /* ConvertInterfaceLuidToGuid */
2609 memset( &guid, 0xff, sizeof(guid) );
2610 ret = ConvertInterfaceLuidToGuid( NULL, &guid );
2611 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2612 ok( guid.Data1 == 0xffffffff, "got %s\n", debugstr_guid(&guid) );
2613
2614 ret = ConvertInterfaceLuidToGuid( &luid, NULL );
2615 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2616
2617 memset( &guid, 0, sizeof(guid) );
2618 ret = ConvertInterfaceLuidToGuid( &luid, &guid );
2619 ok( !ret, "got %lu\n", ret );
2620 ok( IsEqualGUID( &guid, &row->InterfaceGuid ), "mismatch\n" );
2621
2622 /* ConvertInterfaceGuidToLuid */
2623 luid.Info.NetLuidIndex = 1;
2624 ret = ConvertInterfaceGuidToLuid( NULL, &luid );
2625 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2626 ok( luid.Info.NetLuidIndex == 1, "got %u\n", luid.Info.NetLuidIndex );
2627
2628 ret = ConvertInterfaceGuidToLuid( &guid, NULL );
2629 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2630
2631 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
2632 ret = ConvertInterfaceGuidToLuid( &guid, &luid );
2633 ok( !ret, "got %lu\n", ret );
2634 ok( luid.Value == row->InterfaceLuid.Value ||
2635 broken( luid.Value != row->InterfaceLuid.Value), /* Win8 can have identical guids for two different ifaces */
2636 "mismatch\n" );
2637 if (luid.Value != row->InterfaceLuid.Value) continue;
2638
2639 /* ConvertInterfaceLuidToNameW */
2640 ret = ConvertInterfaceLuidToNameW( &luid, NULL, 0 );
2641 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2642
2643 ret = ConvertInterfaceLuidToNameW( &luid, nameW, 0 );
2644 ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %lu\n", ret );
2645
2646 nameW[0] = 0;
2647 len = ARRAY_SIZE(nameW);
2648 ret = ConvertInterfaceLuidToNameW( &luid, nameW, len );
2649 ok( !ret, "got %lu\n", ret );
2650 convert_luid_to_name( &luid, expect_nameW, len );
2651 ok( !wcscmp( nameW, expect_nameW ), "got %s vs %s\n", debugstr_w( nameW ), debugstr_w( expect_nameW ) );
2652
2653 /* ConvertInterfaceLuidToNameA */
2654 ret = ConvertInterfaceLuidToNameA( &luid, NULL, 0 );
2655 ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %lu\n", ret );
2656
2657 ret = ConvertInterfaceLuidToNameA( &luid, nameA, 0 );
2658 ok( ret == ERROR_NOT_ENOUGH_MEMORY, "got %lu\n", ret );
2659
2660 nameA[0] = 0;
2661 len = ARRAY_SIZE(nameA);
2662 ret = ConvertInterfaceLuidToNameA( &luid, nameA, len );
2663 ok( !ret, "got %lu\n", ret );
2664 ok( nameA[0], "name not set\n" );
2665
2666 /* ConvertInterfaceNameToLuidW */
2667 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
2668 ret = ConvertInterfaceNameToLuidW( NULL, &luid );
2669 ok( ret == ERROR_INVALID_NAME, "got %lu\n", ret );
2670 ok( !luid.Info.Reserved, "got %x\n", luid.Info.Reserved );
2671 ok( luid.Info.NetLuidIndex != 0xdead, "index not set\n" );
2672 ok( !luid.Info.IfType, "got %u\n", luid.Info.IfType );
2673
2674 ret = ConvertInterfaceNameToLuidW( nameW, NULL );
2675 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2676
2677 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
2678 ret = ConvertInterfaceNameToLuidW( nameW, &luid );
2679 ok( !ret, "got %lu\n", ret );
2680 ok( luid.Value == row->InterfaceLuid.Value, "mismatch\n" );
2681
2682 /* ConvertInterfaceNameToLuidA */
2683 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
2684 ret = ConvertInterfaceNameToLuidA( NULL, &luid );
2685 ok( ret == ERROR_INVALID_NAME, "got %lu\n", ret );
2686#if defined(__REACTOS__) && defined(_MSC_VER)
2687 ok( luid.Info.Reserved == 0xffdead, "reserved set\n" );
2688 ok( luid.Info.NetLuidIndex == 0xffdead, "index set\n" );
2689#else
2690 ok( luid.Info.Reserved == 0xdead, "reserved set\n" );
2691 ok( luid.Info.NetLuidIndex == 0xdead, "index set\n" );
2692#endif
2693 ok( luid.Info.IfType == 0xdead, "type set\n" );
2694
2695 ret = ConvertInterfaceNameToLuidA( nameA, NULL );
2696 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2697
2698 luid.Info.Reserved = luid.Info.NetLuidIndex = luid.Info.IfType = 0xdead;
2699 ret = ConvertInterfaceNameToLuidA( nameA, &luid );
2700 ok( !ret, "got %lu\n", ret );
2701 ok( luid.Value == row->InterfaceLuid.Value, "mismatch\n" );
2702
2703 /* ConvertInterfaceAliasToLuid */
2704 ret = ConvertInterfaceAliasToLuid( row->Alias, &luid );
2705 ok( !ret, "got %lu\n", ret );
2706 ok( luid.Value == row->InterfaceLuid.Value, "mismatch\n" );
2707
2708 /* ConvertInterfaceLuidToAlias */
2709 ret = ConvertInterfaceLuidToAlias( &row->InterfaceLuid, alias, ARRAY_SIZE(alias) );
2710 ok( !ret, "got %lu\n", ret );
2711 ok( !wcscmp( alias, row->Alias ), "got %s vs %s\n", wine_dbgstr_w( alias ), wine_dbgstr_w( row->Alias ) );
2712
2713 index = if_nametoindex( nameA );
2714 ok( index == row->InterfaceIndex, "Got index %lu for %s, expected %lu\n", index, nameA, row->InterfaceIndex );
2715 /* Wargaming.net Game Center passes a GUID-like string. */
2716 index = if_nametoindex( "{00000001-0000-0000-0000-000000000000}" );
2717 ok( !index, "Got unexpected index %lu\n", index );
2718 index = if_nametoindex( wine_dbgstr_guid( &guid ) );
2719 ok( !index, "Got unexpected index %lu for input %s\n", index, wine_dbgstr_guid( &guid ) );
2720
2721 /* if_indextoname */
2722 nameA[0] = 0;
2723 name = if_indextoname( row->InterfaceIndex, nameA );
2724 ConvertInterfaceLuidToNameA( &row->InterfaceLuid, expect_nameA, ARRAY_SIZE(expect_nameA) );
2725 ok( name == nameA, "mismatch\n" );
2726 ok( !strcmp( nameA, expect_nameA ), "mismatch\n" );
2727 }
2728 FreeMibTable( table );
2729}
2730
2731static void test_interface_identifier_conversion_failure(void)
2732{
2733 DWORD ret;
2734 WCHAR nameW[IF_MAX_STRING_SIZE + 1];
2735 char nameA[IF_MAX_STRING_SIZE + 1], *name;
2736 NET_IFINDEX index;
2737 NET_LUID luid;
2738 GUID guid;
2739 static const GUID guid_zero;
2740 static const GUID guid_ones = { 0xffffffffUL, 0xffff, 0xffff, { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
2741
2742#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
2743 if (!ConvertInterfaceIndexToLuid || !ConvertInterfaceLuidToIndex ||
2744 !ConvertInterfaceLuidToGuid || !ConvertInterfaceGuidToLuid ||
2745 !ConvertInterfaceLuidToNameW || !ConvertInterfaceLuidToNameA ||
2746 !ConvertInterfaceNameToLuidW || !ConvertInterfaceNameToLuidA ||
2747 !if_nametoindex || !if_indextoname) {
2748 skip("Missing APIs!\n");
2749 return;
2750 }
2751#endif
2752 /* ConvertInterfaceIndexToLuid */
2753 ret = ConvertInterfaceIndexToLuid( 0, NULL );
2754 ok( ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", ret );
2755
2756 ret = ConvertInterfaceIndexToLuid( -1, &luid );
2757 ok( ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %lu\n", ret );
2758
2759 /* ConvertInterfaceLuidToIndex */
2760 ret = ConvertInterfaceLuidToIndex( NULL, NULL );
2761 ok( ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", ret );
2762
2763 ret = ConvertInterfaceLuidToIndex( NULL, &index );
2764 ok( ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", ret );
2765
2766 luid.Value = -1;
2767 index = -1;
2768 ret = ConvertInterfaceLuidToIndex( &luid, &index );
2769 ok( ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %lu\n", ret );
2770 ok( index == 0, "index shall be zero (got %lu)\n", index );
2771
2772 /* ConvertInterfaceLuidToGuid */
2773 ret = ConvertInterfaceLuidToGuid( NULL, NULL );
2774 ok( ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", ret );
2775
2776 luid.Value = -1;
2777 memcpy( &guid, &guid_ones, sizeof(guid) );
2778 ret = ConvertInterfaceLuidToGuid( &luid, &guid );
2779 ok( ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %lu\n", ret );
2780 ok( memcmp( &guid, &guid_zero, sizeof(guid) ) == 0, "guid shall be nil\n" );
2781
2782 /* ConvertInterfaceGuidToLuid */
2783 ret = ConvertInterfaceGuidToLuid( NULL, NULL );
2784 ok( ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", ret );
2785
2786 /* ConvertInterfaceLuidToNameW */
2787 ret = ConvertInterfaceLuidToNameW( NULL, NULL, 0 );
2788 ok( ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", ret );
2789
2790 memset( nameW, 0, sizeof(nameW) );
2791 ret = ConvertInterfaceLuidToNameW( NULL, nameW, 0 );
2792 ok( ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", ret );
2793 ok( !nameW[0], "nameW shall not change\n" );
2794
2795 /* ConvertInterfaceLuidToNameA */
2796 ret = ConvertInterfaceLuidToNameA( NULL, NULL, 0 );
2797 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2798
2799 memset( nameA, 0, sizeof(nameA) );
2800 ret = ConvertInterfaceLuidToNameA( NULL, nameA, 0 );
2801 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2802 ok( !nameA[0], "nameA shall not change\n" );
2803
2804 /* ConvertInterfaceNameToLuidW */
2805 ret = ConvertInterfaceNameToLuidW( NULL, NULL );
2806 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2807
2808 /* ConvertInterfaceNameToLuidA */
2809 ret = ConvertInterfaceNameToLuidA( NULL, NULL );
2810 ok( ret == ERROR_INVALID_NAME, "got %lu\n", ret );
2811
2812 /* if_nametoindex */
2813 index = if_nametoindex( NULL );
2814 ok( !index, "Got unexpected index %lu\n", index );
2815
2816 /* if_indextoname */
2817 name = if_indextoname( 0, NULL );
2818 ok( name == NULL, "expected NULL, got %s\n", name );
2819
2820 name = if_indextoname( 0, nameA );
2821 ok( name == NULL, "expected NULL, got %p\n", name );
2822
2823 name = if_indextoname( ~0u, nameA );
2824 ok( name == NULL, "expected NULL, got %p\n", name );
2825}
2826
2827static void test_GetIfEntry2(void)
2828{
2829 DWORD ret;
2830 MIB_IF_ROW2 row;
2831 NET_IFINDEX index;
2832
2833#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
2834 if (!GetIfEntry2) {
2835 skip("Missing APIs!\n");
2836 return;
2837 }
2838#endif
2839 if (!(index = get_interface_index()))
2840 {
2841 skip( "no suitable interface found\n" );
2842 return;
2843 }
2844
2845 ret = GetIfEntry2( NULL );
2846 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2847
2848 memset( &row, 0, sizeof(row) );
2849 ret = GetIfEntry2( &row );
2850 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2851
2852 memset( &row, 0, sizeof(row) );
2853 row.InterfaceIndex = index;
2854 ret = GetIfEntry2( &row );
2855 ok( ret == NO_ERROR, "got %lu\n", ret );
2856 ok( row.InterfaceIndex == index, "got %lu\n", index );
2857}
2858
2859static void test_GetIfTable2(void)
2860{
2861 DWORD ret;
2862 MIB_IF_TABLE2 *table;
2863
2864#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
2865 if (!GetIfTable2) {
2866 skip("Missing APIs!\n");
2867 return;
2868 }
2869#endif
2870 table = NULL;
2871 ret = GetIfTable2( &table );
2872 ok( ret == NO_ERROR, "got %lu\n", ret );
2873 ok( table != NULL, "table not set\n" );
2874 FreeMibTable( table );
2875}
2876
2877static void test_GetIfTable2Ex(void)
2878{
2879 DWORD ret;
2880 MIB_IF_TABLE2 *table;
2881
2882#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
2883 if (!GetIfTable2Ex) {
2884 skip("Missing APIs!\n");
2885 return;
2886 }
2887#endif
2888 table = NULL;
2889 ret = GetIfTable2Ex( MibIfTableNormal, &table );
2890 ok( ret == NO_ERROR, "got %lu\n", ret );
2891 ok( table != NULL, "table not set\n" );
2892 FreeMibTable( table );
2893
2894 table = NULL;
2895 ret = GetIfTable2Ex( MibIfTableRaw, &table );
2896 ok( ret == NO_ERROR, "got %lu\n", ret );
2897 ok( table != NULL, "table not set\n" );
2898 FreeMibTable( table );
2899
2900 table = NULL;
2901 ret = GetIfTable2Ex( MibIfTableNormalWithoutStatistics, &table );
2902 ok( ret == NO_ERROR || broken(ret == ERROR_INVALID_PARAMETER), "got %lu\n", ret );
2903 ok( table != NULL || broken(!table), "table not set\n" );
2904 FreeMibTable( table );
2905
2906 table = NULL;
2907 ret = GetIfTable2Ex( 3, &table );
2908 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2909 ok( !table, "table should not be set\n" );
2910 FreeMibTable( table );
2911}
2912
2913static void test_GetUnicastIpAddressEntry(void)
2914{
2915 IP_ADAPTER_ADDRESSES *aa, *ptr;
2916 MIB_UNICASTIPADDRESS_ROW row;
2917 DWORD ret;
2918
2919 if (!pGetUnicastIpAddressEntry)
2920 {
2921 win_skip( "GetUnicastIpAddressEntry not available\n" );
2922 return;
2923 }
2924
2925 ret = pGetUnicastIpAddressEntry( NULL );
2926 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2927
2928 memset( &row, 0, sizeof(row) );
2929 ret = pGetUnicastIpAddressEntry( &row );
2930 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2931
2932 memset( &row, 0, sizeof(row) );
2933 row.Address.Ipv4.sin_family = AF_INET;
2934 row.Address.Ipv4.sin_port = 0;
2935 row.Address.Ipv4.sin_addr.S_un.S_addr = 0x01020304;
2936 ret = pGetUnicastIpAddressEntry( &row );
2937 ok( ret == ERROR_FILE_NOT_FOUND, "got %lu\n", ret );
2938
2939 memset( &row, 0, sizeof(row) );
2940 row.InterfaceIndex = 123;
2941 ret = pGetUnicastIpAddressEntry( &row );
2942 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
2943
2944 memset( &row, 0, sizeof(row) );
2945 row.InterfaceIndex = get_interface_index();
2946 row.Address.Ipv4.sin_family = AF_INET;
2947 row.Address.Ipv4.sin_port = 0;
2948 row.Address.Ipv4.sin_addr.S_un.S_addr = 0x01020304;
2949 ret = pGetUnicastIpAddressEntry( &row );
2950 ok( ret == ERROR_NOT_FOUND, "got %lu\n", ret );
2951
2952 memset( &row, 0, sizeof(row) );
2953 row.InterfaceIndex = 123;
2954 row.Address.Ipv4.sin_family = AF_INET;
2955 row.Address.Ipv4.sin_port = 0;
2956 row.Address.Ipv4.sin_addr.S_un.S_addr = 0x01020304;
2957 ret = pGetUnicastIpAddressEntry( &row );
2958 ok( ret == ERROR_FILE_NOT_FOUND, "got %lu\n", ret );
2959
2960 ptr = get_adapters( GAA_FLAG_INCLUDE_ALL_INTERFACES );
2961 ok(ptr != NULL, "can't get adapters\n");
2962
2963 for (aa = ptr; !ret && aa; aa = aa->Next)
2964 {
2965 IP_ADAPTER_UNICAST_ADDRESS *ua;
2966
2967 ua = aa->FirstUnicastAddress;
2968 while (ua)
2969 {
2970 /* test with luid */
2971 memset( &row, 0, sizeof(row) );
2972 memcpy(&row.InterfaceLuid, &aa->Luid, sizeof(aa->Luid));
2973 memcpy(&row.Address, ua->Address.lpSockaddr, ua->Address.iSockaddrLength);
2974 ret = pGetUnicastIpAddressEntry( &row );
2975 ok( ret == NO_ERROR, "got %lu\n", ret );
2976
2977 /* test with index */
2978 memset( &row, 0, sizeof(row) );
2979 row.InterfaceIndex = aa->IfIndex;
2980 memcpy(&row.Address, ua->Address.lpSockaddr, ua->Address.iSockaddrLength);
2981 ret = pGetUnicastIpAddressEntry( &row );
2982 ok( ret == NO_ERROR, "got %lu\n", ret );
2983 if (ret == NO_ERROR)
2984 {
2985 ok(row.InterfaceLuid.Info.Reserved == aa->Luid.Info.Reserved, "Expected %d, got %d\n",
2986 aa->Luid.Info.Reserved, row.InterfaceLuid.Info.Reserved);
2987 ok(row.InterfaceLuid.Info.NetLuidIndex == aa->Luid.Info.NetLuidIndex, "Expected %d, got %d\n",
2988 aa->Luid.Info.NetLuidIndex, row.InterfaceLuid.Info.NetLuidIndex);
2989 ok(row.InterfaceLuid.Info.IfType == aa->Luid.Info.IfType, "Expected %d, got %d\n",
2990 aa->Luid.Info.IfType, row.InterfaceLuid.Info.IfType);
2991 ok(row.InterfaceIndex == aa->IfIndex, "Expected %ld, got %ld\n",
2992 aa->IfIndex, row.InterfaceIndex);
2993 ok(row.PrefixOrigin == ua->PrefixOrigin, "Expected %d, got %d\n",
2994 ua->PrefixOrigin, row.PrefixOrigin);
2995 ok(row.SuffixOrigin == ua->SuffixOrigin, "Expected %d, got %d\n",
2996 ua->SuffixOrigin, row.SuffixOrigin);
2997 ok(row.ValidLifetime == ua->ValidLifetime, "Expected %ld, got %ld\n",
2998 ua->ValidLifetime, row.ValidLifetime);
2999 ok(row.PreferredLifetime == ua->PreferredLifetime, "Expected %ld, got %ld\n",
3000 ua->PreferredLifetime, row.PreferredLifetime);
3001 ok(row.OnLinkPrefixLength == ua->OnLinkPrefixLength, "Expected %d, got %d\n",
3002 ua->OnLinkPrefixLength, row.OnLinkPrefixLength);
3003 ok(row.SkipAsSource == 0, "Expected 0, got %d\n", row.SkipAsSource);
3004 ok(row.DadState == ua->DadState, "Expected %d, got %d\n", ua->DadState, row.DadState);
3005 if (row.Address.si_family == AF_INET6)
3006 ok(row.ScopeId.Value == row.Address.Ipv6.sin6_scope_id, "Expected %ld, got %ld\n",
3007 row.Address.Ipv6.sin6_scope_id, row.ScopeId.Value);
3008 ok(row.CreationTimeStamp.QuadPart, "CreationTimeStamp is 0\n");
3009 }
3010 ua = ua->Next;
3011 }
3012 }
3013 free(ptr);
3014}
3015
3016static void test_GetUnicastIpAddressTable(void)
3017{
3018 MIB_UNICASTIPADDRESS_TABLE *table;
3019 DWORD ret;
3020 ULONG i;
3021
3022 if (!pGetUnicastIpAddressTable)
3023 {
3024 win_skip( "GetUnicastIpAddressTable not available\n" );
3025 return;
3026 }
3027
3028 ret = pGetUnicastIpAddressTable(AF_UNSPEC, NULL);
3029 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
3030
3031 ret = pGetUnicastIpAddressTable(AF_BAN, &table);
3032 ok( ret == ERROR_INVALID_PARAMETER, "got %lu\n", ret );
3033
3034 ret = pGetUnicastIpAddressTable(AF_INET, &table);
3035 ok( ret == NO_ERROR, "got %lu\n", ret );
3036 trace("GetUnicastIpAddressTable(AF_INET): NumEntries %lu\n", table->NumEntries);
3037 FreeMibTable( table );
3038
3039 ret = pGetUnicastIpAddressTable(AF_INET6, &table);
3040 ok( ret == NO_ERROR, "got %lu\n", ret );
3041 trace("GetUnicastIpAddressTable(AF_INET6): NumEntries %lu\n", table->NumEntries);
3042 FreeMibTable( table );
3043
3044 ret = pGetUnicastIpAddressTable(AF_UNSPEC, &table);
3045 ok( ret == NO_ERROR, "got %lu\n", ret );
3046 trace("GetUnicastIpAddressTable(AF_UNSPEC): NumEntries %lu\n", table->NumEntries);
3047 for (i = 0; i < table->NumEntries && winetest_debug > 1; i++)
3048 {
3049 trace("Index %lu:\n", i);
3050 trace("Address.si_family: %u\n", table->Table[i].Address.si_family);
3051 trace("InterfaceLuid.Info.Reserved: %u\n", table->Table[i].InterfaceLuid.Info.Reserved);
3052 trace("InterfaceLuid.Info.NetLuidIndex: %u\n", table->Table[i].InterfaceLuid.Info.NetLuidIndex);
3053 trace("InterfaceLuid.Info.IfType: %u\n", table->Table[i].InterfaceLuid.Info.IfType);
3054 trace("InterfaceIndex: %lu\n", table->Table[i].InterfaceIndex);
3055 trace("PrefixOrigin: %u\n", table->Table[i].PrefixOrigin);
3056 trace("SuffixOrigin: %u\n", table->Table[i].SuffixOrigin);
3057 trace("ValidLifetime: %lu seconds\n", table->Table[i].ValidLifetime);
3058 trace("PreferredLifetime: %lu seconds\n", table->Table[i].PreferredLifetime);
3059 trace("OnLinkPrefixLength: %u\n", table->Table[i].OnLinkPrefixLength);
3060 trace("SkipAsSource: %u\n", table->Table[i].SkipAsSource);
3061 trace("DadState: %u\n", table->Table[i].DadState);
3062 trace("ScopeId.Value: %lu\n", table->Table[i].ScopeId.Value);
3063 trace("CreationTimeStamp: %08lx%08lx\n", table->Table[i].CreationTimeStamp.HighPart, table->Table[i].CreationTimeStamp.LowPart);
3064 }
3065
3066 FreeMibTable( table );
3067}
3068
3069static void test_ConvertLengthToIpv4Mask(void)
3070{
3071 DWORD ret;
3072 DWORD n;
3073 ULONG mask;
3074 ULONG expected;
3075
3076 if (!pConvertLengthToIpv4Mask)
3077 {
3078 win_skip( "ConvertLengthToIpv4Mask not available\n" );
3079 return;
3080 }
3081
3082 for (n = 0; n <= 32; n++)
3083 {
3084 mask = 0xdeadbeef;
3085 if (n > 0)
3086 expected = htonl( ~0u << (32 - n) );
3087 else
3088 expected = 0;
3089
3090 ret = pConvertLengthToIpv4Mask( n, &mask );
3091 ok( ret == NO_ERROR, "ConvertLengthToIpv4Mask returned 0x%08lx, expected 0x%08x\n", ret, NO_ERROR );
3092 ok( mask == expected, "ConvertLengthToIpv4Mask mask value 0x%08lx, expected 0x%08lx\n", mask, expected );
3093 }
3094
3095 /* Testing for out of range. In this case both mask and return are changed to indicate error. */
3096 mask = 0xdeadbeef;
3097 ret = pConvertLengthToIpv4Mask( 33, &mask );
3098 ok( ret == ERROR_INVALID_PARAMETER, "ConvertLengthToIpv4Mask returned 0x%08lx, expected 0x%08x\n", ret, ERROR_INVALID_PARAMETER );
3099 ok( mask == INADDR_NONE, "ConvertLengthToIpv4Mask mask value 0x%08lx, expected 0x%08x\n", mask, INADDR_NONE );
3100}
3101
3102static void test_GetTcp6Table(void)
3103{
3104 DWORD ret;
3105 ULONG size = 0;
3106 PMIB_TCP6TABLE buf;
3107
3108 if (!pGetTcp6Table)
3109 {
3110 win_skip("GetTcp6Table not available\n");
3111 return;
3112 }
3113
3114 ret = pGetTcp6Table(NULL, &size, FALSE);
3115 if (ret == ERROR_NOT_SUPPORTED)
3116 {
3117 skip("GetTcp6Table is not supported\n");
3118 return;
3119 }
3120 ok(ret == ERROR_INSUFFICIENT_BUFFER,
3121 "GetTcp6Table(NULL, &size, FALSE) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n", ret);
3122 if (ret != ERROR_INSUFFICIENT_BUFFER) return;
3123
3124 buf = malloc(size);
3125
3126 ret = pGetTcp6Table(buf, &size, FALSE);
3127 ok(ret == NO_ERROR,
3128 "GetTcp6Table(buf, &size, FALSE) returned %ld, expected NO_ERROR\n", ret);
3129
3130 if (ret == NO_ERROR && winetest_debug > 1)
3131 {
3132 DWORD i;
3133 trace("TCP6 table: %lu entries\n", buf->dwNumEntries);
3134 for (i = 0; i < buf->dwNumEntries; i++)
3135 {
3136 trace("%lu: local %s%%%u:%u remote %s%%%u:%u state %u\n", i,
3137 ntoa6(&buf->table[i].LocalAddr), ntohs(buf->table[i].dwLocalScopeId),
3138 ntohs(buf->table[i].dwLocalPort), ntoa6(&buf->table[i].RemoteAddr),
3139 ntohs(buf->table[i].dwRemoteScopeId), ntohs(buf->table[i].dwRemotePort),
3140 buf->table[i].State);
3141 }
3142 }
3143
3144 free(buf);
3145}
3146
3147static void test_GetUdp6Table(void)
3148{
3149 DWORD apiReturn;
3150 ULONG dwSize = 0;
3151
3152 if (!pGetUdp6Table) {
3153 win_skip("GetUdp6Table not available\n");
3154 return;
3155 }
3156
3157 apiReturn = pGetUdp6Table(NULL, &dwSize, FALSE);
3158 if (apiReturn == ERROR_NOT_SUPPORTED) {
3159 skip("GetUdp6Table is not supported\n");
3160 return;
3161 }
3162 ok(apiReturn == ERROR_INSUFFICIENT_BUFFER,
3163 "GetUdp6Table(NULL, &dwSize, FALSE) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
3164 apiReturn);
3165 if (apiReturn == ERROR_INSUFFICIENT_BUFFER) {
3166 PMIB_UDP6TABLE buf = malloc(dwSize);
3167
3168 apiReturn = pGetUdp6Table(buf, &dwSize, FALSE);
3169 ok(apiReturn == NO_ERROR,
3170 "GetUdp6Table(buf, &dwSize, FALSE) returned %ld, expected NO_ERROR\n",
3171 apiReturn);
3172
3173 if (apiReturn == NO_ERROR && winetest_debug > 1)
3174 {
3175 DWORD i;
3176 trace( "UDP6 table: %lu entries\n", buf->dwNumEntries );
3177 for (i = 0; i < buf->dwNumEntries; i++)
3178 trace( "%lu: %s%%%u:%u\n",
3179 i, ntoa6(&buf->table[i].dwLocalAddr), ntohs(buf->table[i].dwLocalScopeId), ntohs(buf->table[i].dwLocalPort) );
3180 }
3181 free(buf);
3182 }
3183}
3184
3185static void test_ParseNetworkString(void)
3186{
3187 struct
3188 {
3189 char str[32];
3190 IN_ADDR addr;
3191 DWORD ret;
3192 }
3193 ipv4_address_tests[] =
3194 {
3195 {"1.2.3.4", {{{1, 2, 3, 4}}}},
3196#if defined(__REACTOS__) && defined(_MSC_VER) && _MSC_VER < 1930
3197 {"1.2.3.4a", {0}, ERROR_INVALID_PARAMETER},
3198 {"1.2.3.0x4a", {0}, ERROR_INVALID_PARAMETER},
3199 {"1.2.3", {0}, ERROR_INVALID_PARAMETER},
3200 {"a1.2.3.4", {0}, ERROR_INVALID_PARAMETER},
3201 {"0xdeadbeef", {0}, ERROR_INVALID_PARAMETER},
3202 {"1.2.3.4:22", {0}, ERROR_INVALID_PARAMETER},
3203 {"::1", {0}, ERROR_INVALID_PARAMETER},
3204 {"winehq.org", {0}, ERROR_INVALID_PARAMETER},
3205#else
3206 {"1.2.3.4a", {}, ERROR_INVALID_PARAMETER},
3207 {"1.2.3.0x4a", {}, ERROR_INVALID_PARAMETER},
3208 {"1.2.3", {}, ERROR_INVALID_PARAMETER},
3209 {"a1.2.3.4", {}, ERROR_INVALID_PARAMETER},
3210 {"0xdeadbeef", {}, ERROR_INVALID_PARAMETER},
3211 {"1.2.3.4:22", {}, ERROR_INVALID_PARAMETER},
3212 {"::1", {}, ERROR_INVALID_PARAMETER},
3213 {"winehq.org", {}, ERROR_INVALID_PARAMETER},
3214#endif
3215 };
3216 struct
3217 {
3218 char str[32];
3219 IN_ADDR addr;
3220 DWORD port;
3221 DWORD ret;
3222 }
3223 ipv4_service_tests[] =
3224 {
3225 {"1.2.3.4:22", {{{1, 2, 3, 4}}}, 22},
3226#if defined(__REACTOS__) && defined(_MSC_VER) && _MSC_VER < 1930
3227 {"winehq.org:22", {0}, 0, ERROR_INVALID_PARAMETER},
3228 {"1.2.3.4", {0}, 0, ERROR_INVALID_PARAMETER},
3229 {"1.2.3.4:0", {0}, 0, ERROR_INVALID_PARAMETER},
3230 {"1.2.3.4:65536", {0}, 0, ERROR_INVALID_PARAMETER},
3231#else
3232 {"winehq.org:22", {}, 0, ERROR_INVALID_PARAMETER},
3233 {"1.2.3.4", {}, 0, ERROR_INVALID_PARAMETER},
3234 {"1.2.3.4:0", {}, 0, ERROR_INVALID_PARAMETER},
3235 {"1.2.3.4:65536", {}, 0, ERROR_INVALID_PARAMETER},
3236#endif
3237 };
3238 WCHAR wstr[IP6_ADDRESS_STRING_BUFFER_LENGTH] = {'1','2','7','.','0','.','0','.','1',':','2','2',0};
3239 NET_ADDRESS_INFO info;
3240 USHORT port;
3241 BYTE prefix_len;
3242 DWORD ret;
3243 int i;
3244
3245 if (!pParseNetworkString)
3246 {
3247 win_skip("ParseNetworkString not available\n");
3248 return;
3249 }
3250
3251 ret = pParseNetworkString(wstr, -1, NULL, NULL, NULL);
3252 ok(ret == ERROR_SUCCESS, "expected success, got %ld\n", ret);
3253
3254 ret = pParseNetworkString(NULL, NET_STRING_IPV4_SERVICE, &info, NULL, NULL);
3255 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
3256
3257 for (i = 0; i < ARRAY_SIZE(ipv4_address_tests); i++)
3258 {
3259 MultiByteToWideChar(CP_ACP, 0, ipv4_address_tests[i].str, sizeof(ipv4_address_tests[i].str),
3260 wstr, ARRAY_SIZE(wstr));
3261 memset(&info, 0x99, sizeof(info));
3262 port = 0x9999;
3263 prefix_len = 0x99;
3264
3265 ret = pParseNetworkString(wstr, NET_STRING_IPV4_ADDRESS, &info, &port, &prefix_len);
3266
3267 ok(ret == ipv4_address_tests[i].ret,
3268 "%s gave error %ld\n", ipv4_address_tests[i].str, ret);
3269 ok(info.Format == ret ? NET_ADDRESS_FORMAT_UNSPECIFIED : NET_ADDRESS_IPV4,
3270 "%s gave format %d\n", ipv4_address_tests[i].str, info.Format);
3271 ok(info.Ipv4Address.sin_addr.S_un.S_addr == (ret ? 0x99999999 : ipv4_address_tests[i].addr.S_un.S_addr),
3272 "%s gave address %d.%d.%d.%d\n", ipv4_address_tests[i].str,
3273 info.Ipv4Address.sin_addr.S_un.S_un_b.s_b1, info.Ipv4Address.sin_addr.S_un.S_un_b.s_b2,
3274 info.Ipv4Address.sin_addr.S_un.S_un_b.s_b3, info.Ipv4Address.sin_addr.S_un.S_un_b.s_b4);
3275 ok(info.Ipv4Address.sin_port == (ret ? 0x9999 : 0),
3276 "%s gave port %d\n", ipv4_service_tests[i].str, ntohs(info.Ipv4Address.sin_port));
3277 ok(port == (ret ? 0x9999 : 0),
3278 "%s gave port %d\n", ipv4_service_tests[i].str, port);
3279 ok(prefix_len == (ret ? 0x99 : 255),
3280 "%s gave prefix length %d\n", ipv4_service_tests[i].str, prefix_len);
3281 }
3282
3283 for (i = 0; i < ARRAY_SIZE(ipv4_service_tests); i++)
3284 {
3285 MultiByteToWideChar(CP_ACP, 0, ipv4_service_tests[i].str, sizeof(ipv4_service_tests[i].str),
3286 wstr, ARRAY_SIZE(wstr));
3287 memset(&info, 0x99, sizeof(info));
3288 port = 0x9999;
3289 prefix_len = 0x99;
3290
3291 ret = pParseNetworkString(wstr, NET_STRING_IPV4_SERVICE, &info, &port, &prefix_len);
3292
3293 ok(ret == ipv4_service_tests[i].ret,
3294 "%s gave error %ld\n", ipv4_service_tests[i].str, ret);
3295 ok(info.Format == ret ? NET_ADDRESS_FORMAT_UNSPECIFIED : NET_ADDRESS_IPV4,
3296 "%s gave format %d\n", ipv4_address_tests[i].str, info.Format);
3297 ok(info.Ipv4Address.sin_addr.S_un.S_addr == (ret ? 0x99999999 : ipv4_service_tests[i].addr.S_un.S_addr),
3298 "%s gave address %d.%d.%d.%d\n", ipv4_service_tests[i].str,
3299 info.Ipv4Address.sin_addr.S_un.S_un_b.s_b1, info.Ipv4Address.sin_addr.S_un.S_un_b.s_b2,
3300 info.Ipv4Address.sin_addr.S_un.S_un_b.s_b3, info.Ipv4Address.sin_addr.S_un.S_un_b.s_b4);
3301 ok(ntohs(info.Ipv4Address.sin_port) == (ret ? 0x9999 : ipv4_service_tests[i].port),
3302 "%s gave port %d\n", ipv4_service_tests[i].str, ntohs(info.Ipv4Address.sin_port));
3303 ok(port == (ret ? 0x9999 : ipv4_service_tests[i].port),
3304 "%s gave port %d\n", ipv4_service_tests[i].str, port);
3305 ok(prefix_len == (ret ? 0x99 : 255),
3306 "%s gave prefix length %d\n", ipv4_service_tests[i].str, prefix_len);
3307 }
3308}
3309
3310static void WINAPI test_ipaddtess_change_callback(PVOID context, PMIB_UNICASTIPADDRESS_ROW row,
3311 MIB_NOTIFICATION_TYPE notification_type)
3312{
3313 BOOL *callback_called = context;
3314
3315 *callback_called = TRUE;
3316
3317 ok(notification_type == MibInitialNotification, "Unexpected notification_type %#x.\n",
3318 notification_type);
3319 ok(!row, "Unexpected row %p.\n", row);
3320}
3321
3322static void test_NotifyUnicastIpAddressChange(void)
3323{
3324 BOOL callback_called;
3325 HANDLE handle;
3326 DWORD ret;
3327
3328 if (!pNotifyUnicastIpAddressChange)
3329 {
3330 win_skip("NotifyUnicastIpAddressChange not available.\n");
3331 return;
3332 }
3333
3334 callback_called = FALSE;
3335 ret = pNotifyUnicastIpAddressChange(AF_INET, test_ipaddtess_change_callback,
3336 &callback_called, TRUE, &handle);
3337 ok(ret == NO_ERROR, "Unexpected ret %#lx.\n", ret);
3338 ok(callback_called, "Callback was not called.\n");
3339
3340 ret = pCancelMibChangeNotify2(handle);
3341 ok(ret == NO_ERROR, "Unexpected ret %#lx.\n", ret);
3342 ok(!CloseHandle(handle), "CloseHandle() succeeded.\n");
3343}
3344
3345static void test_ConvertGuidToString( void )
3346{
3347 DWORD err;
3348 char bufA[39];
3349 WCHAR bufW[39];
3350 GUID guid = { 0xa, 0xb, 0xc, { 0xd, 0, 0xe, 0xf } }, guid2;
3351
3352#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
3353 if (!ConvertGuidToStringA || !ConvertGuidToStringW) {
3354 skip("Missing APIs!\n");
3355 return;
3356 }
3357#endif
3358 err = ConvertGuidToStringA( &guid, bufA, 38 );
3359 ok( err, "got %ld\n", err );
3360 err = ConvertGuidToStringA( &guid, bufA, 39 );
3361 ok( !err, "got %ld\n", err );
3362 ok( !strcmp( bufA, "{0000000A-000B-000C-0D00-0E0F00000000}" ), "got %s\n", bufA );
3363
3364 err = ConvertGuidToStringW( &guid, bufW, 38 );
3365 ok( err, "got %ld\n", err );
3366 err = ConvertGuidToStringW( &guid, bufW, 39 );
3367 ok( !err, "got %ld\n", err );
3368 ok( !wcscmp( bufW, L"{0000000A-000B-000C-0D00-0E0F00000000}" ), "got %s\n", debugstr_w( bufW ) );
3369
3370 err = ConvertStringToGuidW( bufW, &guid2 );
3371 ok( !err, "got %ld\n", err );
3372 ok( IsEqualGUID( &guid, &guid2 ), "guid mismatch\n" );
3373
3374 err = ConvertStringToGuidW( L"foo", &guid2 );
3375 ok( err == ERROR_INVALID_PARAMETER, "got %ld\n", err );
3376}
3377
3378static void test_compartments(void)
3379{
3380 NET_IF_COMPARTMENT_ID id;
3381
3382#if defined(__REACTOS__) && (DLL_EXPORT_VERSION < _WIN32_WINNT_VISTA)
3383 if (!GetCurrentThreadCompartmentId) {
3384 skip("Missing APIs!\n");
3385 return;
3386 }
3387#endif
3388 id = GetCurrentThreadCompartmentId();
3389 ok(id == NET_IF_COMPARTMENT_ID_PRIMARY, "got %u\n", id);
3390}
3391
3392START_TEST(iphlpapi)
3393{
3394 WSADATA wsa_data;
3395 WSAStartup(MAKEWORD(2, 2), &wsa_data);
3396
3397 loadIPHlpApi();
3398 if (hLibrary) {
3399 HANDLE thread;
3400
3401 testWin98OnlyFunctions();
3402 testWinNT4Functions();
3403
3404 /* run testGetXXXX in two threads at once to make sure we don't crash in that case */
3405 thread = CreateThread(NULL, 0, testWin98Functions, NULL, 0, NULL);
3406 testWin98Functions(NULL);
3407 WaitForSingleObject(thread, INFINITE);
3408
3409 testWin2KFunctions();
3410 test_GetAdaptersAddresses();
3411 test_GetExtendedTcpTable();
3412 test_GetExtendedTcpTable_owner(AF_INET);
3413 test_GetExtendedTcpTable_owner(AF_INET6);
3414 test_GetExtendedUdpTable();
3415 test_GetExtendedUdpTable_owner(AF_INET);
3416 test_GetExtendedUdpTable_owner(AF_INET6);
3417 test_AllocateAndGetTcpExTableFromStack();
3418 test_CreateSortedAddressPairs();
3419 test_interface_identifier_conversion();
3420 test_interface_identifier_conversion_failure();
3421 test_GetIfEntry2();
3422 test_GetIfTable2();
3423 test_GetIfTable2Ex();
3424 test_GetUnicastIpAddressEntry();
3425 test_GetUnicastIpAddressTable();
3426 test_ConvertLengthToIpv4Mask();
3427 test_GetTcp6Table();
3428 test_GetUdp6Table();
3429 test_ParseNetworkString();
3430 test_NotifyUnicastIpAddressChange();
3431 test_ConvertGuidToString();
3432 test_compartments();
3433 freeIPHlpApi();
3434 }
3435
3436 WSACleanup();
3437}