Reactos
at master 3437 lines 141 kB view raw
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}