Reactos
at master 3344 lines 99 kB view raw
1/* 2 * iphlpapi dll implementation 3 * 4 * Copyright (C) 2003 Juan Lang 5 * 2018 Pierre Schweitzer 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#define DEBUG 23 24#include <config.h> 25#include "iphlpapi_private.h" 26#include <strsafe.h> 27#include <psapi.h> 28 29WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); 30 31typedef struct _NAME_SERVER_LIST_CONTEXT { 32 ULONG uSizeAvailable; 33 ULONG uSizeRequired; 34 PIP_PER_ADAPTER_INFO pData; 35 UINT NumServers; 36 IP_ADDR_STRING *pLastAddr; 37} NAME_SERVER_LIST_CONTEXT, *PNAME_SERVER_LIST_CONTEXT; 38 39BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 40{ 41 switch (fdwReason) { 42 case DLL_PROCESS_ATTACH: 43 DisableThreadLibraryCalls( hinstDLL ); 44 interfaceMapInit(); 45 break; 46 47 case DLL_PROCESS_DETACH: 48 interfaceMapFree(); 49 break; 50 } 51 return TRUE; 52} 53 54/****************************************************************** 55 * AddIPAddress (IPHLPAPI.@) 56 * 57 * PARAMS 58 * Address [In] 59 * IpMask [In] 60 * IfIndex [In] 61 * NTEContext [In/Out] 62 * NTEInstance [In/Out] 63 * 64 * RETURNS 65 * DWORD 66 */ 67DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance) 68{ 69 return RtlNtStatusToDosError(addIPAddress(Address, Netmask, IfIndex, NteContext, NteInstance)); 70} 71 72DWORD getInterfaceGatewayByIndex(DWORD index) 73{ 74 DWORD ndx, retVal = 0, numRoutes = getNumRoutes(); 75 RouteTable *table = getRouteTable(); 76 if (!table) return 0; 77 78 for (ndx = 0; ndx < numRoutes; ndx++) 79 { 80 if ((table->routes[ndx].ifIndex == (index)) && (table->routes[ndx].dest == 0)) 81 retVal = table->routes[ndx].gateway; 82 } 83 HeapFree(GetProcessHeap(), 0, table); 84 return retVal; 85} 86 87/****************************************************************** 88 * AllocateAndGetIfTableFromStack (IPHLPAPI.@) 89 * 90 * PARAMS 91 * ppIfTable [Out] -- pointer into which the MIB_IFTABLE is 92 * allocated and returned. 93 * bOrder [In] -- passed to GetIfTable to order the table 94 * heap [In] -- heap from which the table is allocated 95 * flags [In] -- flags to HeapAlloc 96 * 97 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever 98 * GetIfTable returns otherwise 99 */ 100DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable, 101 BOOL bOrder, HANDLE heap, DWORD flags) 102{ 103 DWORD ret; 104 105 TRACE("ppIfTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n", ppIfTable, 106 (DWORD)bOrder, heap, flags); 107 if (!ppIfTable) 108 ret = ERROR_INVALID_PARAMETER; 109 else { 110 DWORD dwSize = 0; 111 112 *ppIfTable = NULL; 113 ret = GetIfTable(*ppIfTable, &dwSize, bOrder); 114 if (ret == ERROR_INSUFFICIENT_BUFFER) { 115 *ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize); 116 ret = GetIfTable(*ppIfTable, &dwSize, bOrder); 117 if (ret != NO_ERROR) { 118 HeapFree(heap, flags, *ppIfTable); 119 *ppIfTable = NULL; 120 } 121 } 122 } 123 TRACE("returning %ld\n", ret); 124 return ret; 125} 126 127 128/****************************************************************** 129 * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@) 130 * 131 * PARAMS 132 * ppIpAddrTable [Out] 133 * bOrder [In] -- passed to GetIpAddrTable to order the table 134 * heap [In] -- heap from which the table is allocated 135 * flags [In] -- flags to HeapAlloc 136 * 137 * RETURNS 138 * DWORD 139 */ 140DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable, 141 BOOL bOrder, HANDLE heap, DWORD flags) 142{ 143 DWORD ret; 144 145 TRACE("ppIpAddrTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n", 146 ppIpAddrTable, (DWORD)bOrder, heap, flags); 147 if (!ppIpAddrTable) 148 ret = ERROR_INVALID_PARAMETER; 149 else { 150 DWORD dwSize = 0; 151 152 *ppIpAddrTable = NULL; 153 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder); 154 if (ret == ERROR_INSUFFICIENT_BUFFER) { 155 *ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize); 156 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder); 157 if (ret != NO_ERROR) { 158 HeapFree(heap, flags, *ppIpAddrTable); 159 *ppIpAddrTable = NULL; 160 } 161 } 162 } 163 TRACE("returning %ld\n", ret); 164 return ret; 165} 166 167 168/****************************************************************** 169 * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@) 170 * 171 * ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is 172 * allocated and returned. 173 * bOrder [In] -- passed to GetIfTable to order the table 174 * heap [In] -- heap from which the table is allocated 175 * flags [In] -- flags to HeapAlloc 176 * 177 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever 178 * GetIpForwardTable returns otherwise 179 */ 180DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE * 181 ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags) 182{ 183 DWORD ret; 184 185 TRACE("ppIpForwardTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n", 186 ppIpForwardTable, (DWORD)bOrder, heap, flags); 187 if (!ppIpForwardTable) 188 ret = ERROR_INVALID_PARAMETER; 189 else { 190 DWORD dwSize = 0; 191 192 *ppIpForwardTable = NULL; 193 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder); 194 if (ret == ERROR_INSUFFICIENT_BUFFER) { 195 *ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize); 196 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder); 197 if (ret != NO_ERROR) { 198 HeapFree(heap, flags, *ppIpForwardTable); 199 *ppIpForwardTable = NULL; 200 } 201 } 202 } 203 TRACE("returning %ld\n", ret); 204 return ret; 205} 206 207 208/****************************************************************** 209 * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@) 210 * 211 * PARAMS 212 * ppIpNetTable [Out] 213 * bOrder [In] -- passed to GetIpNetTable to order the table 214 * heap [In] -- heap from which the table is allocated 215 * flags [In] -- flags to HeapAlloc 216 * 217 * RETURNS 218 * DWORD 219 */ 220DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable, 221 BOOL bOrder, HANDLE heap, DWORD flags) 222{ 223 DWORD ret; 224 225 TRACE("ppIpNetTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n", 226 ppIpNetTable, (DWORD)bOrder, heap, flags); 227 if (!ppIpNetTable) 228 ret = ERROR_INVALID_PARAMETER; 229 else { 230 DWORD dwSize = 0; 231 232 *ppIpNetTable = NULL; 233 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder); 234 if (ret == ERROR_INSUFFICIENT_BUFFER) { 235 *ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize); 236 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder); 237 if (ret != NO_ERROR) { 238 HeapFree(heap, flags, *ppIpNetTable); 239 *ppIpNetTable = NULL; 240 } 241 } 242 } 243 TRACE("returning %ld\n", ret); 244 return ret; 245} 246 247 248/****************************************************************** 249 * AllocateAndGetTcpTableFromStack (IPHLPAPI.@) 250 * 251 * PARAMS 252 * ppTcpTable [Out] 253 * bOrder [In] -- passed to GetTcpTable to order the table 254 * heap [In] -- heap from which the table is allocated 255 * flags [In] -- flags to HeapAlloc 256 * 257 * RETURNS 258 * DWORD 259 */ 260DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable, 261 BOOL bOrder, HANDLE heap, DWORD flags) 262{ 263 DWORD ret; 264 265 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n", 266 ppTcpTable, (DWORD)bOrder, heap, flags); 267 if (!ppTcpTable) 268 ret = ERROR_INVALID_PARAMETER; 269 else { 270 DWORD dwSize = 0; 271 272 *ppTcpTable = NULL; 273 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder); 274 if (ret == ERROR_INSUFFICIENT_BUFFER) { 275 *ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize); 276 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder); 277 if (ret != NO_ERROR) { 278 HeapFree(heap, flags, *ppTcpTable); 279 *ppTcpTable = NULL; 280 } 281 } 282 } 283 TRACE("returning %ld\n", ret); 284 return ret; 285} 286 287 288/****************************************************************** 289 * AllocateAndGetTcpExTableFromStack (IPHLPAPI.@) 290 * 291 * PARAMS 292 * ppTcpTable [Out] 293 * bOrder [In] -- passed to GetExtendedTcpTable to order the table 294 * heap [In] -- heap from which the table is allocated 295 * flags [In] -- flags to HeapAlloc 296 * family [In] -- passed to GetExtendedTcpTable to select INET family 297 * 298 * RETURNS 299 * DWORD 300 */ 301DWORD WINAPI AllocateAndGetTcpExTableFromStack(PVOID *ppTcpTable, 302 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family) 303{ 304 DWORD ret; 305 306 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family 0x%08lx\n", 307 ppTcpTable, (DWORD)bOrder, heap, flags, family); 308 if (!ppTcpTable) 309 ret = ERROR_INVALID_PARAMETER; 310 else { 311 DWORD dwSize = 0; 312 313 *ppTcpTable = NULL; 314 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0); 315 if (ret == ERROR_INSUFFICIENT_BUFFER) { 316 *ppTcpTable = (PMIB_TCPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize); 317 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0); 318 if (ret != NO_ERROR) { 319 HeapFree(heap, flags, *ppTcpTable); 320 *ppTcpTable = NULL; 321 } 322 } 323 } 324 TRACE("returning %ld\n", ret); 325 return ret; 326} 327 328 329/****************************************************************** 330 * AllocateAndGetTcpExTable2FromStack (IPHLPAPI.@) 331 * 332 * PARAMS 333 * ppTcpTable [Out] 334 * bOrder [In] -- passed to GetExtendedTcpTable to order the table 335 * heap [In] -- heap from which the table is allocated 336 * flags [In] -- flags to HeapAlloc 337 * family [In] -- passed to GetExtendedTcpTable to select INET family 338 * class [In] -- passed to GetExtendedTcpTable to select information 339 * 340 * RETURNS 341 * DWORD 342 */ 343DWORD WINAPI AllocateAndGetTcpExTable2FromStack(PVOID *ppTcpTable, 344 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, TCP_TABLE_CLASS class) 345{ 346 DWORD ret; 347 348 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family %ld, class %ld\n", 349 ppTcpTable, (DWORD)bOrder, heap, flags, family, class); 350 if (!ppTcpTable) 351 ret = ERROR_INVALID_PARAMETER; 352 else { 353 DWORD dwSize = 0; 354 355 *ppTcpTable = NULL; 356 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0); 357 if (ret == ERROR_INSUFFICIENT_BUFFER) { 358 *ppTcpTable = HeapAlloc(heap, flags, dwSize); 359 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0); 360 if (ret != NO_ERROR) { 361 HeapFree(heap, flags, *ppTcpTable); 362 *ppTcpTable = NULL; 363 } 364 } 365 } 366 TRACE("returning %ld\n", ret); 367 return ret; 368} 369 370 371/****************************************************************** 372 * AllocateAndGetUdpTableFromStack (IPHLPAPI.@) 373 * 374 * PARAMS 375 * ppUdpTable [Out] 376 * bOrder [In] -- passed to GetUdpTable to order the table 377 * heap [In] -- heap from which the table is allocated 378 * flags [In] -- flags to HeapAlloc 379 * 380 * RETURNS 381 * DWORD 382 */ 383DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable, 384 BOOL bOrder, HANDLE heap, DWORD flags) 385{ 386 DWORD ret; 387 388 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n", 389 ppUdpTable, (DWORD)bOrder, heap, flags); 390 if (!ppUdpTable) 391 ret = ERROR_INVALID_PARAMETER; 392 else { 393 DWORD dwSize = 0; 394 395 *ppUdpTable = NULL; 396 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder); 397 if (ret == ERROR_INSUFFICIENT_BUFFER) { 398 *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize); 399 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder); 400 if (ret != NO_ERROR) { 401 HeapFree(heap, flags, *ppUdpTable); 402 *ppUdpTable = NULL; 403 } 404 } 405 } 406 TRACE("returning %ld\n", ret); 407 return ret; 408} 409 410 411/****************************************************************** 412 * AllocateAndGetUdpExTableFromStack (IPHLPAPI.@) 413 * 414 * PARAMS 415 * ppUdpTable [Out] 416 * bOrder [In] -- passed to GetExtendedUdpTable to order the table 417 * heap [In] -- heap from which the table is allocated 418 * flags [In] -- flags to HeapAlloc 419 * family [In] -- passed to GetExtendedUdpTable to select INET family 420 * 421 * RETURNS 422 * DWORD 423 */ 424DWORD WINAPI AllocateAndGetUdpExTableFromStack(PVOID *ppUdpTable, 425 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family) 426{ 427 DWORD ret; 428 429 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family 0x%08lx\n", 430 ppUdpTable, (DWORD)bOrder, heap, flags, family); 431 if (!ppUdpTable) 432 ret = ERROR_INVALID_PARAMETER; 433 else { 434 DWORD dwSize = 0; 435 436 *ppUdpTable = NULL; 437 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0); 438 if (ret == ERROR_INSUFFICIENT_BUFFER) { 439 *ppUdpTable = (PMIB_UDPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize); 440 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0); 441 if (ret != NO_ERROR) { 442 HeapFree(heap, flags, *ppUdpTable); 443 *ppUdpTable = NULL; 444 } 445 } 446 } 447 TRACE("returning %ld\n", ret); 448 return ret; 449} 450 451 452/****************************************************************** 453 * AllocateAndGetUdpExTable2FromStack (IPHLPAPI.@) 454 * 455 * PARAMS 456 * ppUdpTable [Out] 457 * bOrder [In] -- passed to GetExtendedUdpTable to order the table 458 * heap [In] -- heap from which the table is allocated 459 * flags [In] -- flags to HeapAlloc 460 * family [In] -- passed to GetExtendedUdpTable to select INET family 461 * class [In] -- passed to GetExtendedUdpTable to select information 462 * 463 * RETURNS 464 * DWORD 465 */ 466DWORD WINAPI AllocateAndGetUdpExTable2FromStack(PVOID *ppUdpTable, 467 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, UDP_TABLE_CLASS class) 468{ 469 DWORD ret; 470 471 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family %ld, class %ld\n", 472 ppUdpTable, (DWORD)bOrder, heap, flags, family, class); 473 if (!ppUdpTable) 474 ret = ERROR_INVALID_PARAMETER; 475 else { 476 DWORD dwSize = 0; 477 478 *ppUdpTable = NULL; 479 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0); 480 if (ret == ERROR_INSUFFICIENT_BUFFER) { 481 *ppUdpTable = HeapAlloc(heap, flags, dwSize); 482 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0); 483 if (ret != NO_ERROR) { 484 HeapFree(heap, flags, *ppUdpTable); 485 *ppUdpTable = NULL; 486 } 487 } 488 } 489 TRACE("returning %ld\n", ret); 490 return ret; 491} 492 493 494/****************************************************************** 495 * CreateIpForwardEntry (IPHLPAPI.@) 496 * 497 * PARAMS 498 * pRoute [In/Out] 499 * 500 * RETURNS 501 * DWORD 502 */ 503DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute) 504{ 505 return createIpForwardEntry( pRoute ); 506} 507 508 509/****************************************************************** 510 * CreateIpNetEntry (IPHLPAPI.@) 511 * 512 * PARAMS 513 * pArpEntry [In/Out] 514 * 515 * RETURNS 516 * DWORD 517 */ 518DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry) 519{ 520 TRACE("pArpEntry %p\n", pArpEntry); 521 /* could use SIOCSARP on systems that support it, not sure I want to */ 522 FIXME(":stub\n"); 523 return (DWORD) 0; 524} 525 526 527/****************************************************************** 528 * CreateProxyArpEntry (IPHLPAPI.@) 529 * 530 * PARAMS 531 * dwAddress [In] 532 * dwMask [In] 533 * dwIfIndex [In] 534 * 535 * RETURNS 536 * DWORD 537 */ 538DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex) 539{ 540 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress, 541 dwMask, dwIfIndex); 542 FIXME(":stub\n"); 543 /* marking Win2K+ functions not supported */ 544 return ERROR_NOT_SUPPORTED; 545} 546 547 548/****************************************************************** 549 * DeleteIPAddress (IPHLPAPI.@) 550 * 551 * PARAMS 552 * NTEContext [In] 553 * 554 * RETURNS 555 * DWORD 556 */ 557DWORD WINAPI DeleteIPAddress(ULONG NTEContext) 558{ 559 TRACE("NTEContext %ld\n", NTEContext); 560 return RtlNtStatusToDosError(deleteIpAddress(NTEContext)); 561} 562 563 564/****************************************************************** 565 * DeleteIpForwardEntry (IPHLPAPI.@) 566 * 567 * PARAMS 568 * pRoute [In/Out] 569 * 570 * RETURNS 571 * DWORD 572 */ 573DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute) 574{ 575 return deleteIpForwardEntry( pRoute ); 576} 577 578 579/****************************************************************** 580 * DeleteIpNetEntry (IPHLPAPI.@) 581 * 582 * PARAMS 583 * pArpEntry [In/Out] 584 * 585 * RETURNS 586 * DWORD 587 */ 588DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry) 589{ 590 TRACE("pArpEntry %p\n", pArpEntry); 591 /* could use SIOCDARP on systems that support it, not sure I want to */ 592 FIXME(":stub\n"); 593 return (DWORD) 0; 594} 595 596 597/****************************************************************** 598 * DeleteProxyArpEntry (IPHLPAPI.@) 599 * 600 * PARAMS 601 * dwAddress [In] 602 * dwMask [In] 603 * dwIfIndex [In] 604 * 605 * RETURNS 606 * DWORD 607 */ 608DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex) 609{ 610 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress, 611 dwMask, dwIfIndex); 612 FIXME(":stub\n"); 613 /* marking Win2K+ functions not supported */ 614 return ERROR_NOT_SUPPORTED; 615} 616 617/****************************************************************** 618 * EnableRouter (IPHLPAPI.@) 619 * 620 * PARAMS 621 * pHandle [In/Out] 622 * pOverlapped [In/Out] 623 * 624 * RETURNS 625 * DWORD 626 */ 627DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped) 628{ 629 TRACE("pHandle %p, pOverlapped %p\n", pHandle, pOverlapped); 630 FIXME(":stub\n"); 631 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to 632 could map EACCESS to ERROR_ACCESS_DENIED, I suppose 633 marking Win2K+ functions not supported */ 634 return ERROR_NOT_SUPPORTED; 635} 636 637 638/****************************************************************** 639 * FlushIpNetTable (IPHLPAPI.@) 640 * 641 * PARAMS 642 * dwIfIndex [In] 643 * 644 * RETURNS 645 * DWORD 646 */ 647DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex) 648{ 649 TRACE("dwIfIndex 0x%08lx\n", dwIfIndex); 650 FIXME(":stub\n"); 651 /* this flushes the arp cache of the given index 652 marking Win2K+ functions not supported */ 653 return ERROR_NOT_SUPPORTED; 654} 655 656 657/****************************************************************** 658 * GetAdapterIndex (IPHLPAPI.@) 659 * 660 * PARAMS 661 * AdapterName [In/Out] 662 * IfIndex [In/Out] 663 * 664 * RETURNS 665 * DWORD 666 */ 667DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex) 668{ 669 TRACE("AdapterName %p, IfIndex %p\n", AdapterName, IfIndex); 670 FIXME(":stub\n"); 671 /* marking Win2K+ functions not supported */ 672 return ERROR_NOT_SUPPORTED; 673} 674 675 676/****************************************************************** 677 * GetAdaptersInfo (IPHLPAPI.@) 678 * 679 * PARAMS 680 * pAdapterInfo [In/Out] 681 * pOutBufLen [In/Out] 682 * 683 * RETURNS 684 * DWORD 685 */ 686DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) 687{ 688 DWORD ret; 689 690 TRACE("pAdapterInfo %p, pOutBufLen %p\n", pAdapterInfo, pOutBufLen); 691 if (!pOutBufLen) 692 ret = ERROR_INVALID_PARAMETER; 693 else { 694 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces(); 695 696 if (numNonLoopbackInterfaces > 0) { 697 /* this calculation assumes only one address in the IP_ADDR_STRING lists. 698 that's okay, because: 699 - we don't get multiple addresses per adapter anyway 700 - we don't know about per-adapter gateways 701 - DHCP and WINS servers can have max one entry per list */ 702 ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces; 703 704 if (!pAdapterInfo || *pOutBufLen < size) { 705 *pOutBufLen = size; 706 ret = ERROR_BUFFER_OVERFLOW; 707 } 708 else { 709 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable(); 710 711 if (table) { 712 size = sizeof(IP_ADAPTER_INFO) * table->numIndexes; 713 if (*pOutBufLen < size) { 714 *pOutBufLen = size; 715 ret = ERROR_INSUFFICIENT_BUFFER; 716 } 717 else { 718 DWORD ndx; 719 HKEY hKey; 720 BOOL winsEnabled = FALSE; 721 IP_ADDRESS_STRING primaryWINS, secondaryWINS; 722 723 memset(pAdapterInfo, 0, size); 724 /* @@ Wine registry key: HKCU\Software\Wine\Network */ 725 if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Network", &hKey) == ERROR_SUCCESS) { 726 DWORD size = sizeof(primaryWINS.String); 727 unsigned long addr; 728 729 RegQueryValueExA(hKey, "WinsServer", NULL, NULL, 730 (PBYTE)primaryWINS.String, &size); 731 addr = inet_addr(primaryWINS.String); 732 if (addr != INADDR_NONE && addr != INADDR_ANY) 733 winsEnabled = TRUE; 734 size = sizeof(secondaryWINS.String); 735 RegQueryValueExA(hKey, "BackupWinsServer", NULL, NULL, 736 (PBYTE)secondaryWINS.String, &size); 737 addr = inet_addr(secondaryWINS.String); 738 if (addr != INADDR_NONE && addr != INADDR_ANY) 739 winsEnabled = TRUE; 740 RegCloseKey(hKey); 741 } 742 TRACE("num of index is %lu\n", table->numIndexes); 743 for (ndx = 0; ndx < table->numIndexes; ndx++) { 744 PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx]; 745 DWORD addrLen = sizeof(ptr->Address), type; 746 const char *ifname = 747 getInterfaceNameByIndex(table->indexes[ndx]); 748 if (!ifname) { 749 ret = ERROR_OUTOFMEMORY; 750 break; 751 } 752 753 /* on Win98 this is left empty, but whatever */ 754 strncpy(ptr->AdapterName,ifname,sizeof(ptr->AdapterName)); 755 consumeInterfaceName(ifname); 756 ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0'; 757 getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen, 758 ptr->Address, &type); 759 /* MS defines address length and type as UINT in some places and 760 DWORD in others, **sigh**. Don't want to assume that PUINT and 761 PDWORD are equiv (64-bit?) */ 762 ptr->AddressLength = addrLen; 763 ptr->Type = type; 764 ptr->Index = table->indexes[ndx]; 765 toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]), 766 ptr->IpAddressList.IpAddress.String); 767 toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]), 768 ptr->IpAddressList.IpMask.String); 769 ptr->IpAddressList.Context = ptr->Index; 770 toIPAddressString(getInterfaceGatewayByIndex(table->indexes[ndx]), 771 ptr->GatewayList.IpAddress.String); 772 getDhcpInfoForAdapter(table->indexes[ndx], ptr); 773 if (winsEnabled) { 774 ptr->HaveWins = TRUE; 775 memcpy(ptr->PrimaryWinsServer.IpAddress.String, 776 primaryWINS.String, sizeof(primaryWINS.String)); 777 memcpy(ptr->SecondaryWinsServer.IpAddress.String, 778 secondaryWINS.String, sizeof(secondaryWINS.String)); 779 } 780 if (ndx < table->numIndexes - 1) 781 ptr->Next = &pAdapterInfo[ndx + 1]; 782 else 783 ptr->Next = NULL; 784 } 785 ret = NO_ERROR; 786 } 787 free(table); 788 } 789 else 790 ret = ERROR_OUTOFMEMORY; 791 } 792 } 793 else 794 ret = ERROR_NO_DATA; 795 } 796 TRACE("returning %ld\n", ret); 797 return ret; 798} 799 800 801/****************************************************************** 802 * GetBestInterface (IPHLPAPI.@) 803 * 804 * PARAMS 805 * dwDestAddr [In] 806 * pdwBestIfIndex [In/Out] 807 * 808 * RETURNS 809 * DWORD 810 */ 811DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex) 812{ 813 DWORD ret; 814 815 TRACE("dwDestAddr 0x%08lx, pdwBestIfIndex %p\n", dwDestAddr, pdwBestIfIndex); 816 if (!pdwBestIfIndex) 817 ret = ERROR_INVALID_PARAMETER; 818 else { 819 MIB_IPFORWARDROW ipRow; 820 821 ret = GetBestRoute(dwDestAddr, 0, &ipRow); 822 if (ret == ERROR_SUCCESS) 823 *pdwBestIfIndex = ipRow.dwForwardIfIndex; 824 } 825 TRACE("returning %ld\n", ret); 826 return ret; 827} 828 829 830/****************************************************************** 831 * GetBestRoute (IPHLPAPI.@) 832 * 833 * PARAMS 834 * dwDestAddr [In] 835 * dwSourceAddr [In] 836 * OUT [In] 837 * 838 * RETURNS 839 * DWORD 840 */ 841DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute) 842{ 843 PMIB_IPFORWARDTABLE table; 844 DWORD ret; 845 846 TRACE("dwDestAddr 0x%08lx, dwSourceAddr 0x%08lx, pBestRoute %p\n", dwDestAddr, 847 dwSourceAddr, pBestRoute); 848 if (!pBestRoute) 849 return ERROR_INVALID_PARAMETER; 850 851 AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0); 852 if (table) { 853 DWORD ndx, minMaskSize, matchedNdx = 0; 854 855 for (ndx = 0, minMaskSize = 255; ndx < table->dwNumEntries; ndx++) { 856 if ((dwDestAddr & table->table[ndx].dwForwardMask) == 857 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) { 858 DWORD hostMaskSize; 859 860 if (!_BitScanForward(&hostMaskSize, ntohl(table->table[ndx].dwForwardMask))) 861 { 862 hostMaskSize = 32; 863 } 864 if (hostMaskSize < minMaskSize) { 865 minMaskSize = hostMaskSize; 866 matchedNdx = ndx; 867 } 868 } 869 } 870 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW)); 871 HeapFree(GetProcessHeap(), 0, table); 872 ret = ERROR_SUCCESS; 873 } 874 else 875 ret = ERROR_OUTOFMEMORY; 876 TRACE("returning %ld\n", ret); 877 return ret; 878} 879 880static int TcpTableSorter(const void *a, const void *b) 881{ 882 int ret; 883 884 if (a && b) { 885 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b; 886 887 ret = rowA->dwLocalAddr - rowB->dwLocalAddr; 888 if (ret == 0) { 889 ret = rowA->dwLocalPort - rowB->dwLocalPort; 890 if (ret == 0) { 891 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr; 892 if (ret == 0) 893 ret = rowA->dwRemotePort - rowB->dwRemotePort; 894 } 895 } 896 } 897 else 898 ret = 0; 899 return ret; 900} 901 902/****************************************************************** 903 * GetExtendedTcpTable (IPHLPAPI.@) 904 * 905 * Get the table of TCP endpoints available to the application. 906 * 907 * PARAMS 908 * pTcpTable [Out] table struct with the filtered TCP endpoints available to application 909 * pdwSize [In/Out] estimated size of the structure returned in pTcpTable, in bytes 910 * bOrder [In] whether to order the table 911 * ulAf [in] version of IP used by the TCP endpoints 912 * TableClass [in] type of the TCP table structure from TCP_TABLE_CLASS 913 * Reserved [in] reserved - this value must be zero 914 * 915 * RETURNS 916 * Success: NO_ERROR 917 * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER 918 */ 919DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved) 920{ 921 DWORD i, count, size; 922 DWORD ret = NO_ERROR; 923 924 if (!pdwSize) 925 { 926 return ERROR_INVALID_PARAMETER; 927 } 928 929 if (ulAf != AF_INET) 930 { 931 UNIMPLEMENTED; 932 return ERROR_INVALID_PARAMETER; 933 } 934 935 switch (TableClass) 936 { 937 case TCP_TABLE_BASIC_ALL: 938 { 939 PMIB_TCPTABLE pOurTcpTable = getTcpTable(ClassBasic); 940 PMIB_TCPTABLE pTheirTcpTable = pTcpTable; 941 942 if (pOurTcpTable) 943 { 944 size = FIELD_OFFSET(MIB_TCPTABLE, table) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW); 945 if (size > *pdwSize || !pTheirTcpTable) 946 { 947 *pdwSize = size; 948 ret = ERROR_INSUFFICIENT_BUFFER; 949 } 950 else 951 { 952 memcpy(pTheirTcpTable, pOurTcpTable, size); 953 954 if (bOrder) 955 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 956 sizeof(MIB_TCPROW), TcpTableSorter); 957 } 958 959 HeapFree(GetProcessHeap(),0, pOurTcpTable); 960 } 961 } 962 break; 963 964 case TCP_TABLE_BASIC_CONNECTIONS: 965 { 966 PMIB_TCPTABLE pOurTcpTable = getTcpTable(ClassBasic); 967 PMIB_TCPTABLE pTheirTcpTable = pTcpTable; 968 969 if (pOurTcpTable) 970 { 971 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 972 { 973 if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN) 974 { 975 ++count; 976 } 977 } 978 979 size = FIELD_OFFSET(MIB_TCPTABLE, table) + count * sizeof(MIB_TCPROW); 980 if (size > *pdwSize || !pTheirTcpTable) 981 { 982 *pdwSize = size; 983 ret = ERROR_INSUFFICIENT_BUFFER; 984 } 985 else 986 { 987 pTheirTcpTable->dwNumEntries = count; 988 989 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 990 { 991 if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN) 992 { 993 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW)); 994 ++count; 995 } 996 } 997 ASSERT(count == pTheirTcpTable->dwNumEntries); 998 999 if (bOrder) 1000 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1001 sizeof(MIB_TCPROW), TcpTableSorter); 1002 } 1003 1004 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1005 } 1006 } 1007 break; 1008 1009 case TCP_TABLE_BASIC_LISTENER: 1010 { 1011 PMIB_TCPTABLE pOurTcpTable = getTcpTable(ClassBasic); 1012 PMIB_TCPTABLE pTheirTcpTable = pTcpTable; 1013 1014 if (pOurTcpTable) 1015 { 1016 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1017 { 1018 if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN) 1019 { 1020 ++count; 1021 } 1022 } 1023 1024 size = FIELD_OFFSET(MIB_TCPTABLE, table) + count * sizeof(MIB_TCPROW); 1025 if (size > *pdwSize || !pTheirTcpTable) 1026 { 1027 *pdwSize = size; 1028 ret = ERROR_INSUFFICIENT_BUFFER; 1029 } 1030 else 1031 { 1032 pTheirTcpTable->dwNumEntries = count; 1033 1034 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1035 { 1036 if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN) 1037 { 1038 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW)); 1039 ++count; 1040 } 1041 } 1042 ASSERT(count == pTheirTcpTable->dwNumEntries); 1043 1044 if (bOrder) 1045 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1046 sizeof(MIB_TCPROW), TcpTableSorter); 1047 } 1048 1049 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1050 } 1051 } 1052 break; 1053 1054 case TCP_TABLE_OWNER_PID_ALL: 1055 { 1056 PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getTcpTable(ClassModulePid); 1057 PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable; 1058 1059 if (pOurTcpTable) 1060 { 1061 size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID); 1062 if (size > *pdwSize || !pTheirTcpTable) 1063 { 1064 *pdwSize = size; 1065 ret = ERROR_INSUFFICIENT_BUFFER; 1066 } 1067 else 1068 { 1069 memcpy(pTheirTcpTable, pOurTcpTable, size); 1070 1071 /* Don't sort on PID, so use basic helper */ 1072 if (bOrder) 1073 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1074 sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter); 1075 } 1076 1077 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1078 } 1079 } 1080 break; 1081 1082 case TCP_TABLE_OWNER_PID_CONNECTIONS: 1083 { 1084 PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getTcpTable(ClassModulePid); 1085 PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable; 1086 1087 if (pOurTcpTable) 1088 { 1089 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1090 { 1091 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN) 1092 { 1093 ++count; 1094 } 1095 } 1096 1097 size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table) + count * sizeof(MIB_TCPROW_OWNER_PID); 1098 if (size > *pdwSize || !pTheirTcpTable) 1099 { 1100 *pdwSize = size; 1101 ret = ERROR_INSUFFICIENT_BUFFER; 1102 } 1103 else 1104 { 1105 pTheirTcpTable->dwNumEntries = count; 1106 1107 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1108 { 1109 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN) 1110 { 1111 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_PID)); 1112 ++count; 1113 } 1114 } 1115 ASSERT(count == pTheirTcpTable->dwNumEntries); 1116 1117 /* Don't sort on PID, so use basic helper */ 1118 if (bOrder) 1119 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1120 sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter); 1121 } 1122 1123 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1124 } 1125 } 1126 break; 1127 1128 case TCP_TABLE_OWNER_PID_LISTENER: 1129 { 1130 PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getTcpTable(ClassModulePid); 1131 PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable; 1132 1133 if (pOurTcpTable) 1134 { 1135 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1136 { 1137 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) 1138 { 1139 ++count; 1140 } 1141 } 1142 1143 size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table) + count * sizeof(MIB_TCPROW_OWNER_PID); 1144 if (size > *pdwSize || !pTheirTcpTable) 1145 { 1146 *pdwSize = size; 1147 ret = ERROR_INSUFFICIENT_BUFFER; 1148 } 1149 else 1150 { 1151 pTheirTcpTable->dwNumEntries = count; 1152 1153 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1154 { 1155 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) 1156 { 1157 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_PID)); 1158 ++count; 1159 } 1160 } 1161 ASSERT(count == pTheirTcpTable->dwNumEntries); 1162 1163 /* Don't sort on PID, so use basic helper */ 1164 if (bOrder) 1165 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1166 sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter); 1167 } 1168 1169 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1170 } 1171 } 1172 break; 1173 1174 case TCP_TABLE_OWNER_MODULE_ALL: 1175 { 1176 PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getTcpTable(ClassModule); 1177 PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable; 1178 1179 if (pOurTcpTable) 1180 { 1181 size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE); 1182 if (size > *pdwSize || !pTheirTcpTable) 1183 { 1184 *pdwSize = size; 1185 ret = ERROR_INSUFFICIENT_BUFFER; 1186 } 1187 else 1188 { 1189 memcpy(pTheirTcpTable, pOurTcpTable, size); 1190 1191 /* Don't sort on PID, so use basic helper */ 1192 if (bOrder) 1193 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1194 sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter); 1195 } 1196 1197 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1198 } 1199 } 1200 break; 1201 1202 case TCP_TABLE_OWNER_MODULE_CONNECTIONS: 1203 { 1204 PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getTcpTable(ClassModule); 1205 PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable; 1206 1207 if (pOurTcpTable) 1208 { 1209 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1210 { 1211 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN) 1212 { 1213 ++count; 1214 } 1215 } 1216 1217 size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table) + count * sizeof(MIB_TCPROW_OWNER_MODULE); 1218 if (size > *pdwSize || !pTheirTcpTable) 1219 { 1220 *pdwSize = size; 1221 ret = ERROR_INSUFFICIENT_BUFFER; 1222 } 1223 else 1224 { 1225 pTheirTcpTable->dwNumEntries = count; 1226 1227 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1228 { 1229 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN) 1230 { 1231 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE)); 1232 ++count; 1233 } 1234 } 1235 ASSERT(count == pTheirTcpTable->dwNumEntries); 1236 1237 /* Don't sort on PID, so use basic helper */ 1238 if (bOrder) 1239 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1240 sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter); 1241 } 1242 1243 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1244 } 1245 } 1246 break; 1247 1248 case TCP_TABLE_OWNER_MODULE_LISTENER: 1249 { 1250 PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getTcpTable(ClassModule); 1251 PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable; 1252 1253 if (pOurTcpTable) 1254 { 1255 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1256 { 1257 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) 1258 { 1259 ++count; 1260 } 1261 } 1262 1263 size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table) + count * sizeof(MIB_TCPROW_OWNER_MODULE); 1264 if (size > *pdwSize || !pTheirTcpTable) 1265 { 1266 *pdwSize = size; 1267 ret = ERROR_INSUFFICIENT_BUFFER; 1268 } 1269 else 1270 { 1271 pTheirTcpTable->dwNumEntries = count; 1272 1273 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i) 1274 { 1275 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) 1276 { 1277 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE)); 1278 ++count; 1279 } 1280 } 1281 ASSERT(count == pTheirTcpTable->dwNumEntries); 1282 1283 /* Don't sort on PID, so use basic helper */ 1284 if (bOrder) 1285 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries, 1286 sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter); 1287 } 1288 1289 HeapFree(GetProcessHeap(), 0, pOurTcpTable); 1290 } 1291 } 1292 break; 1293 1294 default: 1295 ret = ERROR_INVALID_PARAMETER; 1296 break; 1297 } 1298 1299 return ret; 1300} 1301 1302static int UdpTableSorter(const void *a, const void *b) 1303{ 1304 int ret; 1305 1306 if (a && b) { 1307 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b; 1308 1309 ret = rowA->dwLocalAddr - rowB->dwLocalAddr; 1310 if (ret == 0) 1311 ret = rowA->dwLocalPort - rowB->dwLocalPort; 1312 } 1313 else 1314 ret = 0; 1315 return ret; 1316} 1317 1318/****************************************************************** 1319 * GetExtendedUdpTable (IPHLPAPI.@) 1320 * 1321 * Get the table of UDP endpoints available to the application. 1322 * 1323 * PARAMS 1324 * pUdpTable [Out] table struct with the filtered UDP endpoints available to application 1325 * pdwSize [In/Out] estimated size of the structure returned in pUdpTable, in bytes 1326 * bOrder [In] whether to order the table 1327 * ulAf [in] version of IP used by the UDP endpoints 1328 * TableClass [in] type of the UDP table structure from UDP_TABLE_CLASS 1329 * Reserved [in] reserved - this value must be zero 1330 * 1331 * RETURNS 1332 * Success: NO_ERROR 1333 * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER 1334 */ 1335DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved) 1336{ 1337 DWORD size; 1338 DWORD ret = NO_ERROR; 1339 1340 if (!pdwSize) 1341 { 1342 return ERROR_INVALID_PARAMETER; 1343 } 1344 1345 if (ulAf != AF_INET) 1346 { 1347 UNIMPLEMENTED; 1348 return ERROR_INVALID_PARAMETER; 1349 } 1350 1351 switch (TableClass) 1352 { 1353 case UDP_TABLE_BASIC: 1354 { 1355 PMIB_UDPTABLE pOurUdpTable = getUdpTable(ClassBasic); 1356 PMIB_UDPTABLE pTheirUdpTable = pUdpTable; 1357 1358 if (pOurUdpTable) 1359 { 1360 size = FIELD_OFFSET(MIB_UDPTABLE, table) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW); 1361 if (size > *pdwSize || !pTheirUdpTable) 1362 { 1363 *pdwSize = size; 1364 ret = ERROR_INSUFFICIENT_BUFFER; 1365 } 1366 else 1367 { 1368 memcpy(pTheirUdpTable, pOurUdpTable, size); 1369 1370 if (bOrder) 1371 qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries, 1372 sizeof(MIB_UDPROW), UdpTableSorter); 1373 } 1374 1375 HeapFree(GetProcessHeap(), 0, pOurUdpTable); 1376 } 1377 } 1378 break; 1379 1380 case UDP_TABLE_OWNER_PID: 1381 { 1382 PMIB_UDPTABLE_OWNER_PID pOurUdpTable = getUdpTable(ClassModulePid); 1383 PMIB_UDPTABLE_OWNER_PID pTheirUdpTable = pUdpTable; 1384 1385 if (pOurUdpTable) 1386 { 1387 size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID); 1388 if (size > *pdwSize || !pTheirUdpTable) 1389 { 1390 *pdwSize = size; 1391 ret = ERROR_INSUFFICIENT_BUFFER; 1392 } 1393 else 1394 { 1395 memcpy(pTheirUdpTable, pOurUdpTable, size); 1396 1397 if (bOrder) 1398 qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries, 1399 sizeof(MIB_UDPROW_OWNER_PID), UdpTableSorter); 1400 } 1401 1402 HeapFree(GetProcessHeap(), 0, pOurUdpTable); 1403 } 1404 } 1405 break; 1406 1407 case UDP_TABLE_OWNER_MODULE: 1408 { 1409 PMIB_UDPTABLE_OWNER_MODULE pOurUdpTable = getUdpTable(ClassModule); 1410 PMIB_UDPTABLE_OWNER_MODULE pTheirUdpTable = pUdpTable; 1411 1412 if (pOurUdpTable) 1413 { 1414 size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE); 1415 if (size > *pdwSize || !pTheirUdpTable) 1416 { 1417 *pdwSize = size; 1418 ret = ERROR_INSUFFICIENT_BUFFER; 1419 } 1420 else 1421 { 1422 memcpy(pTheirUdpTable, pOurUdpTable, size); 1423 1424 if (bOrder) 1425 qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries, 1426 sizeof(MIB_UDPROW_OWNER_MODULE), UdpTableSorter); 1427 } 1428 1429 HeapFree(GetProcessHeap(), 0, pOurUdpTable); 1430 } 1431 } 1432 break; 1433 1434 default: 1435 ret = ERROR_INVALID_PARAMETER; 1436 break; 1437 } 1438 1439 return ret; 1440} 1441 1442 1443/****************************************************************** 1444 * GetFriendlyIfIndex (IPHLPAPI.@) 1445 * 1446 * PARAMS 1447 * IfIndex [In] 1448 * 1449 * RETURNS 1450 * DWORD 1451 */ 1452DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex) 1453{ 1454 /* windows doesn't validate these, either, just makes sure the top byte is 1455 cleared. I assume my ifenum module never gives an index with the top 1456 byte set. */ 1457 TRACE("returning %ld\n", IfIndex); 1458 return IfIndex; 1459} 1460 1461 1462/****************************************************************** 1463 * GetIcmpStatistics (IPHLPAPI.@) 1464 * 1465 * PARAMS 1466 * pStats [In/Out] 1467 * 1468 * RETURNS 1469 * DWORD 1470 */ 1471DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats) 1472{ 1473 DWORD ret; 1474 1475 TRACE("pStats %p\n", pStats); 1476 ret = getICMPStats(pStats); 1477 TRACE("returning %ld\n", ret); 1478 return ret; 1479} 1480 1481 1482/****************************************************************** 1483 * GetIfEntry (IPHLPAPI.@) 1484 * 1485 * PARAMS 1486 * pIfRow [In/Out] 1487 * 1488 * RETURNS 1489 * DWORD 1490 */ 1491DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow) 1492{ 1493 DWORD ret; 1494 const char *name; 1495 1496 TRACE("pIfRow %p\n", pIfRow); 1497 if (!pIfRow) 1498 return ERROR_INVALID_PARAMETER; 1499 1500 name = getInterfaceNameByIndex(pIfRow->dwIndex); 1501 if (name) { 1502 ret = getInterfaceEntryByIndex(pIfRow->dwIndex, pIfRow); 1503 if (ret == NO_ERROR) 1504 ret = getInterfaceStatsByName(name, pIfRow); 1505 consumeInterfaceName(name); 1506 } 1507 else 1508 ret = ERROR_INVALID_DATA; 1509 TRACE("returning %ld\n", ret); 1510 return ret; 1511} 1512 1513 1514static int IfTableSorter(const void *a, const void *b) 1515{ 1516 int ret; 1517 1518 if (a && b) 1519 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex; 1520 else 1521 ret = 0; 1522 return ret; 1523} 1524 1525 1526/****************************************************************** 1527 * GetIfTable (IPHLPAPI.@) 1528 * 1529 * PARAMS 1530 * pIfTable [In/Out] 1531 * pdwSize [In/Out] 1532 * bOrder [In] 1533 * 1534 * RETURNS 1535 * DWORD 1536 */ 1537DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) 1538{ 1539 DWORD ret; 1540 1541 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize, 1542 (DWORD)bOrder); 1543 if (!pdwSize) 1544 ret = ERROR_INVALID_PARAMETER; 1545 else { 1546 DWORD numInterfaces = getNumInterfaces(); 1547 ULONG size; 1548 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces); 1549 size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW); 1550 1551 if (!pIfTable || *pdwSize < size) { 1552 *pdwSize = size; 1553 ret = ERROR_INSUFFICIENT_BUFFER; 1554 } 1555 else { 1556 InterfaceIndexTable *table = getInterfaceIndexTable(); 1557 1558 if (table) { 1559 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) * 1560 sizeof(MIB_IFROW); 1561 if (*pdwSize < size) { 1562 *pdwSize = size; 1563 ret = ERROR_INSUFFICIENT_BUFFER; 1564 } 1565 else { 1566 DWORD ndx; 1567 1568 pIfTable->dwNumEntries = 0; 1569 for (ndx = 0; ndx < table->numIndexes; ndx++) { 1570 pIfTable->table[ndx].dwIndex = table->indexes[ndx]; 1571 GetIfEntry(&pIfTable->table[ndx]); 1572 pIfTable->dwNumEntries++; 1573 } 1574 if (bOrder) 1575 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW), 1576 IfTableSorter); 1577 ret = NO_ERROR; 1578 } 1579 free(table); 1580 } 1581 else 1582 ret = ERROR_OUTOFMEMORY; 1583 } 1584 } 1585 TRACE("returning %ld\n", ret); 1586 return ret; 1587} 1588 1589 1590/****************************************************************** 1591 * GetInterfaceInfo (IPHLPAPI.@) 1592 * 1593 * PARAMS 1594 * pIfTable [In/Out] 1595 * dwOutBufLen [In/Out] 1596 * 1597 * RETURNS 1598 * DWORD 1599 */ 1600DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen) 1601{ 1602 DWORD ret; 1603 1604 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen); 1605 if (!dwOutBufLen) 1606 ret = ERROR_INVALID_PARAMETER; 1607 else { 1608 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces(); 1609 ULONG size; 1610 TRACE("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces); 1611 size = sizeof(IP_INTERFACE_INFO) + (numNonLoopbackInterfaces) * 1612 sizeof(IP_ADAPTER_INDEX_MAP); 1613 1614 if (!pIfTable || *dwOutBufLen < size) { 1615 *dwOutBufLen = size; 1616 ret = ERROR_INSUFFICIENT_BUFFER; 1617 } 1618 else { 1619 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable(); 1620 1621 if (table) { 1622 TRACE("table->numIndexes == 0x%x\n", table->numIndexes); 1623 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes) * 1624 sizeof(IP_ADAPTER_INDEX_MAP); 1625 if (*dwOutBufLen < size) { 1626 *dwOutBufLen = size; 1627 ret = ERROR_INSUFFICIENT_BUFFER; 1628 } 1629 else { 1630 DWORD ndx; 1631 1632 pIfTable->NumAdapters = 0; 1633 for (ndx = 0; ndx < table->numIndexes; ndx++) { 1634 const char *walker, *name; 1635 WCHAR *assigner; 1636 1637 pIfTable->Adapter[ndx].Index = table->indexes[ndx]; 1638 name = getInterfaceNameByIndex(table->indexes[ndx]); 1639 wcscpy(pIfTable->Adapter[ndx].Name, L"\\DEVICE\\TCPIP_"); 1640 for (walker = name, assigner = &pIfTable->Adapter[ndx].Name[14]; 1641 walker && *walker && 1642 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1 - 14; 1643 walker++, assigner++) 1644 *assigner = *walker; 1645 *assigner = 0; 1646 consumeInterfaceName(name); 1647 pIfTable->NumAdapters++; 1648 } 1649 ret = NO_ERROR; 1650 } 1651 free(table); 1652 } 1653 else 1654 ret = ERROR_OUTOFMEMORY; 1655 } 1656 } 1657 TRACE("returning %ld\n", ret); 1658 return ret; 1659} 1660 1661 1662static int IpAddrTableSorter(const void *a, const void *b) 1663{ 1664 int ret; 1665 1666 if (a && b) 1667 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr; 1668 else 1669 ret = 0; 1670 return ret; 1671} 1672 1673 1674/****************************************************************** 1675 * GetIpAddrTable (IPHLPAPI.@) 1676 * 1677 * PARAMS 1678 * pIpAddrTable [In/Out] 1679 * pdwSize [In/Out] 1680 * bOrder [In] 1681 * 1682 * RETURNS 1683 * DWORD 1684 */ 1685DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder) 1686{ 1687 DWORD ret; 1688 1689 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize, 1690 (DWORD)bOrder); 1691 if (!pdwSize) 1692 ret = ERROR_INVALID_PARAMETER; 1693 else { 1694 DWORD numInterfaces = getNumInterfaces(); 1695 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) * 1696 sizeof(MIB_IPADDRROW); 1697 1698 if (!pIpAddrTable || *pdwSize < size) { 1699 *pdwSize = size; 1700 ret = ERROR_INSUFFICIENT_BUFFER; 1701 } 1702 else { 1703 InterfaceIndexTable *table = getInterfaceIndexTable(); 1704 1705 if (table) { 1706 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) * 1707 sizeof(MIB_IPADDRROW); 1708 if (*pdwSize < size) { 1709 *pdwSize = size; 1710 ret = ERROR_INSUFFICIENT_BUFFER; 1711 } 1712 else { 1713 DWORD ndx, bcast; 1714 1715 pIpAddrTable->dwNumEntries = 0; 1716 for (ndx = 0; ndx < table->numIndexes; ndx++) { 1717 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx]; 1718 pIpAddrTable->table[ndx].dwAddr = 1719 getInterfaceIPAddrByIndex(table->indexes[ndx]); 1720 pIpAddrTable->table[ndx].dwMask = 1721 getInterfaceMaskByIndex(table->indexes[ndx]); 1722 /* the dwBCastAddr member isn't the broadcast address, it indicates 1723 * whether the interface uses the 1's broadcast address (1) or the 1724 * 0's broadcast address (0). 1725 */ 1726 bcast = getInterfaceBCastAddrByIndex(table->indexes[ndx]); 1727 pIpAddrTable->table[ndx].dwBCastAddr = 1728 (bcast & pIpAddrTable->table[ndx].dwMask) ? 1 : 0; 1729 /* FIXME: hardcoded reasm size, not sure where to get it */ 1730 pIpAddrTable->table[ndx].dwReasmSize = 65535; 1731 pIpAddrTable->table[ndx].unused1 = 0; 1732 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */ 1733 pIpAddrTable->dwNumEntries++; 1734 } 1735 if (bOrder) 1736 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries, 1737 sizeof(MIB_IPADDRROW), IpAddrTableSorter); 1738 ret = NO_ERROR; 1739 } 1740 free(table); 1741 } 1742 else 1743 ret = ERROR_OUTOFMEMORY; 1744 } 1745 } 1746 TRACE("returning %ld\n", ret); 1747 return ret; 1748} 1749 1750 1751static int IpForwardTableSorter(const void *a, const void *b) 1752{ 1753 int ret; 1754 1755 if (a && b) { 1756 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b; 1757 1758 ret = rowA->dwForwardDest - rowB->dwForwardDest; 1759 if (ret == 0) { 1760 ret = rowA->dwForwardProto - rowB->dwForwardProto; 1761 if (ret == 0) { 1762 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy; 1763 if (ret == 0) 1764 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop; 1765 } 1766 } 1767 } 1768 else 1769 ret = 0; 1770 return ret; 1771} 1772 1773 1774/****************************************************************** 1775 * GetIpForwardTable (IPHLPAPI.@) 1776 * 1777 * PARAMS 1778 * pIpForwardTable [In/Out] 1779 * pdwSize [In/Out] 1780 * bOrder [In] 1781 * 1782 * RETURNS 1783 * DWORD 1784 */ 1785DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder) 1786{ 1787 DWORD ret; 1788 1789 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable, 1790 pdwSize, (DWORD)bOrder); 1791 if (!pdwSize) 1792 ret = ERROR_INVALID_PARAMETER; 1793 else { 1794 DWORD numRoutes = getNumRoutes(); 1795 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * 1796 sizeof(MIB_IPFORWARDROW); 1797 1798 if (!pIpForwardTable || *pdwSize < sizeNeeded) { 1799 *pdwSize = sizeNeeded; 1800 ret = ERROR_INSUFFICIENT_BUFFER; 1801 } 1802 else { 1803 RouteTable *table = getRouteTable(); 1804 if (table) { 1805 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) * 1806 sizeof(MIB_IPFORWARDROW); 1807 if (*pdwSize < sizeNeeded) { 1808 *pdwSize = sizeNeeded; 1809 ret = ERROR_INSUFFICIENT_BUFFER; 1810 } 1811 else { 1812 DWORD ndx; 1813 1814 pIpForwardTable->dwNumEntries = table->numRoutes; 1815 for (ndx = 0; ndx < numRoutes; ndx++) { 1816 pIpForwardTable->table[ndx].dwForwardIfIndex = 1817 table->routes[ndx].ifIndex; 1818 pIpForwardTable->table[ndx].dwForwardDest = 1819 table->routes[ndx].dest; 1820 pIpForwardTable->table[ndx].dwForwardMask = 1821 table->routes[ndx].mask; 1822 pIpForwardTable->table[ndx].dwForwardPolicy = 0; 1823 pIpForwardTable->table[ndx].dwForwardNextHop = 1824 table->routes[ndx].gateway; 1825 /* FIXME: this type is appropriate for local interfaces; may not 1826 always be appropriate */ 1827 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT; 1828 /* FIXME: other protos might be appropriate, e.g. the default route 1829 is typically set with MIB_IPPROTO_NETMGMT instead */ 1830 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL; 1831 /* punt on age and AS */ 1832 pIpForwardTable->table[ndx].dwForwardAge = 0; 1833 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0; 1834 pIpForwardTable->table[ndx].dwForwardMetric1 = 1835 table->routes[ndx].metric; 1836 /* rest of the metrics are 0.. */ 1837 pIpForwardTable->table[ndx].dwForwardMetric2 = 0; 1838 pIpForwardTable->table[ndx].dwForwardMetric3 = 0; 1839 pIpForwardTable->table[ndx].dwForwardMetric4 = 0; 1840 pIpForwardTable->table[ndx].dwForwardMetric5 = 0; 1841 } 1842 if (bOrder) 1843 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries, 1844 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter); 1845 ret = NO_ERROR; 1846 } 1847 HeapFree(GetProcessHeap(), 0, table); 1848 } 1849 else 1850 ret = ERROR_OUTOFMEMORY; 1851 } 1852 } 1853 TRACE("returning %ld\n", ret); 1854 return ret; 1855} 1856 1857 1858static int IpNetTableSorter(const void *a, const void *b) 1859{ 1860 int ret; 1861 1862 if (a && b) 1863 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr; 1864 else 1865 ret = 0; 1866 return ret; 1867} 1868 1869 1870/****************************************************************** 1871 * GetIpNetTable (IPHLPAPI.@) 1872 * 1873 * PARAMS 1874 * pIpNetTable [In/Out] 1875 * pdwSize [In/Out] 1876 * bOrder [In] 1877 * 1878 * RETURNS 1879 * DWORD 1880 */ 1881DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder) 1882{ 1883 DWORD ret = NO_ERROR; 1884 1885 TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize, 1886 (DWORD)bOrder); 1887 if (!pdwSize) 1888 ret = ERROR_INVALID_PARAMETER; 1889 else { 1890 DWORD numEntries = getNumArpEntries(); 1891 ULONG size = sizeof(MIB_IPNETTABLE); 1892 1893 if (numEntries > 1) 1894 size += (numEntries - 1) * sizeof(MIB_IPNETROW); 1895 if (!pIpNetTable || *pdwSize < size) { 1896 *pdwSize = size; 1897 ret = ERROR_INSUFFICIENT_BUFFER; 1898 } 1899 else { 1900 PMIB_IPNETTABLE table = getArpTable(); 1901 if (table) { 1902 size = sizeof(MIB_IPNETTABLE); 1903 if (table->dwNumEntries > 1) 1904 size += (table->dwNumEntries - 1) * sizeof(MIB_IPNETROW); 1905 if (*pdwSize < size) { 1906 *pdwSize = size; 1907 ret = ERROR_INSUFFICIENT_BUFFER; 1908 } 1909 else { 1910 *pdwSize = size; 1911 memcpy(pIpNetTable, table, size); 1912 if (bOrder) 1913 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries, 1914 sizeof(MIB_IPNETROW), IpNetTableSorter); 1915 ret = NO_ERROR; 1916 } 1917 HeapFree(GetProcessHeap(), 0, table); 1918 } 1919 } 1920 } 1921 TRACE("returning %d\n", ret); 1922 return ret; 1923} 1924 1925 1926/****************************************************************** 1927 * GetIpStatistics (IPHLPAPI.@) 1928 * 1929 * PARAMS 1930 * pStats [In/Out] 1931 * 1932 * RETURNS 1933 * DWORD 1934 */ 1935DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats) 1936{ 1937 return GetIpStatisticsEx(pStats, PF_INET); 1938} 1939 1940/****************************************************************** 1941 * GetIpStatisticsEx (IPHLPAPI.@) 1942 * 1943 * PARAMS 1944 * pStats [In/Out] 1945 * dwFamily [In] 1946 * 1947 * RETURNS 1948 * DWORD 1949 */ 1950DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily) 1951{ 1952 HANDLE tcpFile; 1953 DWORD ret; 1954 1955 if (!pStats) 1956 return ERROR_INVALID_PARAMETER; 1957 1958 if (dwFamily != AF_INET && dwFamily != AF_INET6) 1959 return ERROR_INVALID_PARAMETER; 1960 1961 if (!NT_SUCCESS(openTcpFile(&tcpFile, FILE_READ_DATA))) 1962 return ERROR_NOT_SUPPORTED; 1963 1964 TRACE("pStats %p\n", pStats); 1965 ret = getIPStats(tcpFile, pStats); 1966 closeTcpFile(tcpFile); 1967 TRACE("returning %ld\n", ret); 1968 return ret; 1969} 1970 1971/****************************************************************** 1972 * GetNetworkParams (IPHLPAPI.@) 1973 * 1974 * PARAMS 1975 * pFixedInfo [In/Out] 1976 * pOutBufLen [In/Out] 1977 * 1978 * RETURNS 1979 * DWORD 1980 */ 1981DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) 1982{ 1983 DWORD ret, size, type; 1984 LONG regReturn; 1985 HKEY hKey; 1986 PIPHLP_RES_INFO resInfo; 1987 1988 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen); 1989 if (!pOutBufLen) 1990 return ERROR_INVALID_PARAMETER; 1991 1992 resInfo = getResInfo(); 1993 if (!resInfo) 1994 return ERROR_OUTOFMEMORY; 1995 1996 size = sizeof(FIXED_INFO) + (resInfo->riCount > 1 ? (resInfo->riCount-1) * 1997 sizeof(IP_ADDR_STRING) : 0); 1998 if (!pFixedInfo || *pOutBufLen < size) { 1999 *pOutBufLen = size; 2000 disposeResInfo( resInfo ); 2001 return ERROR_BUFFER_OVERFLOW; 2002 } 2003 2004 memset(pFixedInfo, 0, size); 2005 /* Check for DhcpHostname and DhcpDomain first */ 2006 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 2007 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 2008 0, 2009 KEY_READ, 2010 &hKey); 2011 if (regReturn == ERROR_SUCCESS) { 2012 /* Windows doesn't honor DHCP option 12 even if RFC requires it if it is returned by DHCP server! */ 2013#if 0 2014 type = REG_SZ; 2015 size = sizeof(pFixedInfo->HostName); 2016 regReturn = RegQueryValueExA(hKey, 2017 "DhcpHostname", 2018 NULL, 2019 &type, 2020 (LPBYTE)pFixedInfo->HostName, 2021 &size); 2022 if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1)) 2023 { 2024#endif 2025 type = REG_SZ; 2026 size = sizeof(pFixedInfo->HostName); 2027 regReturn = RegQueryValueExA(hKey, 2028 "Hostname", 2029 NULL, 2030 &type, 2031 (LPBYTE)pFixedInfo->HostName, 2032 &size); 2033#if 0 2034 } 2035#endif 2036 2037 type = REG_SZ; 2038 size = sizeof(pFixedInfo->DomainName); 2039 regReturn = RegQueryValueExA(hKey, 2040 "DhcpDomain", 2041 NULL, 2042 &type, 2043 (LPBYTE)pFixedInfo->DomainName, 2044 &size); 2045 if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1)) 2046 { 2047 type = REG_SZ; 2048 size = sizeof(pFixedInfo->DomainName); 2049 regReturn = RegQueryValueExA(hKey, 2050 "Domain", 2051 NULL, 2052 &type, 2053 (LPBYTE)pFixedInfo->DomainName, 2054 &size); 2055 } 2056 RegCloseKey(hKey); 2057 } 2058 2059 TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName); 2060 2061 if (resInfo->riCount > 0) 2062 { 2063 CopyMemory(&pFixedInfo->DnsServerList, resInfo->DnsList, sizeof(IP_ADDR_STRING)); 2064 if (resInfo->riCount > 1) 2065 { 2066 IP_ADDR_STRING *pSrc = resInfo->DnsList->Next; 2067 IP_ADDR_STRING *pTarget = (struct _IP_ADDR_STRING*)((char*)pFixedInfo + sizeof(FIXED_INFO)); 2068 2069 pFixedInfo->DnsServerList.Next = pTarget; 2070 2071 do 2072 { 2073 CopyMemory(pTarget, pSrc, sizeof(IP_ADDR_STRING)); 2074 resInfo->riCount--; 2075 if (resInfo->riCount > 1) 2076 { 2077 pTarget->Next = (IP_ADDR_STRING*)((char*)pTarget + sizeof(IP_ADDR_STRING)); 2078 pTarget = pTarget->Next; 2079 pSrc = pSrc->Next; 2080 } 2081 else 2082 { 2083 pTarget->Next = NULL; 2084 break; 2085 } 2086 } 2087 while(TRUE); 2088 } 2089 else 2090 { 2091 pFixedInfo->DnsServerList.Next = NULL; 2092 } 2093 } 2094 2095 pFixedInfo->NodeType = HYBRID_NODETYPE; 2096 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 2097 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey); 2098 if (regReturn != ERROR_SUCCESS) 2099 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 2100 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ, 2101 &hKey); 2102 if (regReturn == ERROR_SUCCESS) 2103 { 2104 DWORD size = sizeof(pFixedInfo->ScopeId); 2105 2106 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (PBYTE)pFixedInfo->ScopeId, &size); 2107 RegCloseKey(hKey); 2108 } 2109 2110 disposeResInfo( resInfo ); 2111 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward 2112 I suppose could also check for a listener on port 53 to set EnableDns */ 2113 ret = NO_ERROR; 2114 TRACE("returning %ld\n", ret); 2115 2116 return ret; 2117} 2118 2119 2120/****************************************************************** 2121 * GetNumberOfInterfaces (IPHLPAPI.@) 2122 * 2123 * PARAMS 2124 * pdwNumIf [In/Out] 2125 * 2126 * RETURNS 2127 * DWORD 2128 */ 2129DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf) 2130{ 2131 DWORD ret; 2132 2133 TRACE("pdwNumIf %p\n", pdwNumIf); 2134 if (!pdwNumIf) 2135 ret = ERROR_INVALID_PARAMETER; 2136 else { 2137 *pdwNumIf = getNumInterfaces(); 2138 ret = NO_ERROR; 2139 } 2140 TRACE("returning %ld\n", ret); 2141 return ret; 2142} 2143 2144 2145static DWORD GetOwnerModuleFromPidEntry(DWORD OwningPid, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize) 2146{ 2147 HANDLE Process; 2148 DWORD FileLen, PathLen, Error; 2149 WCHAR File[MAX_PATH], Path[MAX_PATH]; 2150 PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo; 2151 2152 if (IsBadWritePtr(pdwSize, sizeof(DWORD)) || 2153 IsBadWritePtr(Buffer, *pdwSize)) 2154 { 2155 return ERROR_INVALID_PARAMETER; 2156 } 2157 2158 if (OwningPid == 0) 2159 { 2160 return ERROR_NOT_FOUND; 2161 } 2162 2163 Process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, OwningPid); 2164 if (Process == NULL) 2165 { 2166 return GetLastError(); 2167 } 2168 2169 FileLen = GetModuleBaseNameW(Process, NULL, File, MAX_PATH); 2170 if (FileLen != 0) 2171 { 2172 PathLen = GetModuleFileNameExW(Process, NULL, Path, MAX_PATH); 2173 if (PathLen == 0) 2174 { 2175 CloseHandle(Process); 2176 return GetLastError(); 2177 } 2178 2179 /* Add NULL char */ 2180 ++FileLen; 2181 ++PathLen; 2182 PathLen *= sizeof(WCHAR); 2183 FileLen *= sizeof(WCHAR); 2184 } 2185 else 2186 { 2187 Error = GetLastError(); 2188 2189 if (Error == ERROR_PARTIAL_COPY) 2190 { 2191 wcscpy(File, L"System"); 2192 wcscpy(Path, L"System"); 2193 2194 PathLen = sizeof(L"System"); 2195 FileLen = sizeof(L"System"); 2196 } 2197 else 2198 { 2199 CloseHandle(Process); 2200 return Error; 2201 } 2202 } 2203 2204 CloseHandle(Process); 2205 2206 if (*pdwSize < sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen) 2207 { 2208 *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen; 2209 return ERROR_INSUFFICIENT_BUFFER; 2210 } 2211 2212 BasicInfo = Buffer; 2213 BasicInfo->pModuleName = (PVOID)((ULONG_PTR)BasicInfo + sizeof(TCPIP_OWNER_MODULE_BASIC_INFO)); 2214 BasicInfo->pModulePath = (PVOID)((ULONG_PTR)BasicInfo->pModuleName + FileLen); 2215 wcscpy(BasicInfo->pModuleName, File); 2216 wcscpy(BasicInfo->pModulePath, Path); 2217 *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen; 2218 2219 return NO_ERROR; 2220} 2221 2222static DWORD GetOwnerModuleFromTagEntry(DWORD OwningPid, DWORD OwningTag, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize) 2223{ 2224 UINT Size; 2225 HRESULT Res; 2226 HANDLE hAdvapi32; 2227 WCHAR SysDir[MAX_PATH]; 2228 PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo; 2229 ULONG (NTAPI *_I_QueryTagInformation)(PVOID, DWORD, PVOID); 2230 struct 2231 { 2232 DWORD ProcessId; 2233 DWORD ServiceTag; 2234 DWORD TagType; 2235 PWSTR Buffer; 2236 } ServiceQuery; 2237 2238 if (IsBadWritePtr(pdwSize, sizeof(DWORD)) || 2239 IsBadWritePtr(Buffer, *pdwSize)) 2240 { 2241 return ERROR_INVALID_PARAMETER; 2242 } 2243 2244 /* First, secure (avoid injections) load advapi32.dll */ 2245 Size = GetSystemDirectoryW(SysDir, MAX_PATH); 2246 if (Size == 0) 2247 { 2248 return GetLastError(); 2249 } 2250 2251 Res = StringCchCatW(&SysDir[Size], MAX_PATH - Size, L"\\advapi32.dll"); 2252 if (FAILED(Res)) 2253 { 2254 return Res; 2255 } 2256 2257 hAdvapi32 = GetModuleHandleW(SysDir); 2258 if (hAdvapi32 == NULL) 2259 { 2260 return GetLastError(); 2261 } 2262 2263 /* Now, we'll query the service associated with the tag */ 2264 _I_QueryTagInformation = (PVOID)GetProcAddress(hAdvapi32, "I_QueryTagInformation"); 2265 if (_I_QueryTagInformation == NULL) 2266 { 2267 return GetLastError(); 2268 } 2269 2270 /* Set tag and PID for the query */ 2271 ServiceQuery.ProcessId = OwningPid; 2272 ServiceQuery.ServiceTag = OwningTag; 2273 ServiceQuery.TagType = 0; 2274 ServiceQuery.Buffer = NULL; 2275 2276 /* And query */ 2277 Res = _I_QueryTagInformation(NULL, 1, &ServiceQuery); 2278 if (Res != ERROR_SUCCESS) 2279 { 2280 return Res; 2281 } 2282 2283 /* Compute service name length */ 2284 Size = wcslen(ServiceQuery.Buffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL); 2285 2286 /* We'll copy it twice, so make sure we have enough room */ 2287 if (*pdwSize < sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + 2 * Size) 2288 { 2289 *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + 2 * Size; 2290 LocalFree(ServiceQuery.Buffer); 2291 return ERROR_INSUFFICIENT_BUFFER; 2292 } 2293 2294 /* Copy back data */ 2295 BasicInfo = Buffer; 2296 BasicInfo->pModuleName = (PVOID)((ULONG_PTR)BasicInfo + sizeof(TCPIP_OWNER_MODULE_BASIC_INFO)); 2297 BasicInfo->pModulePath = (PVOID)((ULONG_PTR)BasicInfo->pModuleName + Size); 2298 wcscpy(BasicInfo->pModuleName, ServiceQuery.Buffer); 2299 wcscpy(BasicInfo->pModulePath, ServiceQuery.Buffer); 2300 *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + 2 * Size; 2301 LocalFree(ServiceQuery.Buffer); 2302 2303 return NO_ERROR; 2304} 2305 2306/****************************************************************** 2307 * GetOwnerModuleFromTcpEntry (IPHLPAPI.@) 2308 * 2309 * Get data about the module that issued the context bind for a specific IPv4 TCP endpoint in a MIB table row 2310 * 2311 * PARAMS 2312 * pTcpEntry [in] pointer to a MIB_TCPROW_OWNER_MODULE structure 2313 * Class [in] TCPIP_OWNER_MODULE_INFO_CLASS enumeration value 2314 * Buffer [out] pointer a buffer containing a TCPIP_OWNER_MODULE_BASIC_INFO structure with the owner module data. 2315 * pdwSize [in, out] estimated size of the structure returned in Buffer, in bytes 2316 * 2317 * RETURNS 2318 * Success: NO_ERROR 2319 * Failure: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY 2320 * ERROR_NOT_FOUND or ERROR_PARTIAL_COPY 2321 * 2322 * NOTES 2323 * The type of data returned in Buffer is indicated by the value of the Class parameter. 2324 */ 2325DWORD WINAPI GetOwnerModuleFromTcpEntry(PMIB_TCPROW_OWNER_MODULE pTcpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize) 2326{ 2327 /* If we have a service tag, that's a service connection */ 2328 if (pTcpEntry->OwningModuleInfo[0] != 0) 2329 { 2330 return GetOwnerModuleFromTagEntry(pTcpEntry->dwOwningPid, (DWORD)(pTcpEntry->OwningModuleInfo[0]), Class, Buffer, pdwSize); 2331 } 2332 else 2333 { 2334 return GetOwnerModuleFromPidEntry(pTcpEntry->dwOwningPid, Class, Buffer, pdwSize); 2335 } 2336} 2337 2338/****************************************************************** 2339 * GetOwnerModuleFromUdpEntry (IPHLPAPI.@) 2340 * 2341 * Get data about the module that issued the context bind for a specific IPv4 UDP endpoint in a MIB table row 2342 * 2343 * PARAMS 2344 * pUdpEntry [in] pointer to a MIB_UDPROW_OWNER_MODULE structure 2345 * Class [in] TCPIP_OWNER_MODULE_INFO_CLASS enumeration value 2346 * Buffer [out] pointer a buffer containing a TCPIP_OWNER_MODULE_BASIC_INFO structure with the owner module data. 2347 * pdwSize [in, out] estimated size of the structure returned in Buffer, in bytes 2348 * 2349 * RETURNS 2350 * Success: NO_ERROR 2351 * Failure: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY 2352 * ERROR_NOT_FOUND or ERROR_PARTIAL_COPY 2353 * 2354 * NOTES 2355 * The type of data returned in Buffer is indicated by the value of the Class parameter. 2356 */ 2357DWORD WINAPI GetOwnerModuleFromUdpEntry(PMIB_UDPROW_OWNER_MODULE pUdpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize) 2358{ 2359 /* If we have a service tag, that's a service connection */ 2360 if (pUdpEntry->OwningModuleInfo[0] != 0) 2361 { 2362 return GetOwnerModuleFromTagEntry(pUdpEntry->dwOwningPid, (DWORD)(pUdpEntry->OwningModuleInfo[0]), Class, Buffer, pdwSize); 2363 } 2364 else 2365 { 2366 return GetOwnerModuleFromPidEntry(pUdpEntry->dwOwningPid, Class, Buffer, pdwSize); 2367 } 2368} 2369 2370static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, PVOID Data) 2371{ 2372 IP_ADDR_STRING *pNext; 2373 PNAME_SERVER_LIST_CONTEXT Context = (PNAME_SERVER_LIST_CONTEXT)Data; 2374 2375 if (!Context->NumServers) 2376 { 2377 if (Context->uSizeAvailable >= Context->uSizeRequired) 2378 { 2379 WideCharToMultiByte(CP_ACP, 0, Server, -1, Context->pData->DnsServerList.IpAddress.String, 16, NULL, NULL); 2380 Context->pData->DnsServerList.IpAddress.String[15] = '\0'; 2381 Context->pLastAddr = &Context->pData->DnsServerList; 2382 } 2383 } 2384 else 2385 { 2386 Context->uSizeRequired += sizeof(IP_ADDR_STRING); 2387 if (Context->uSizeAvailable >= Context->uSizeRequired) 2388 { 2389 pNext = (IP_ADDR_STRING*)(((char*)Context->pLastAddr) + sizeof(IP_ADDR_STRING)); 2390 WideCharToMultiByte(CP_ACP, 0, Server, -1, pNext->IpAddress.String, 16, NULL, NULL); 2391 pNext->IpAddress.String[15] = '\0'; 2392 Context->pLastAddr->Next = pNext; 2393 Context->pLastAddr = pNext; 2394 pNext->Next = NULL; 2395 } 2396 } 2397 Context->NumServers++; 2398} 2399 2400/****************************************************************** 2401 * GetPerAdapterInfo (IPHLPAPI.@) 2402 * 2403 * PARAMS 2404 * IfIndex [In] 2405 * pPerAdapterInfo [In/Out] 2406 * pOutBufLen [In/Out] 2407 * 2408 * RETURNS 2409 * DWORD 2410 */ 2411DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen) 2412{ 2413 HKEY hkey; 2414 DWORD dwSize = 0; 2415 const char *ifName; 2416 NAME_SERVER_LIST_CONTEXT Context; 2417 WCHAR keyname[200] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"; 2418 2419 if (!pOutBufLen) 2420 return ERROR_INVALID_PARAMETER; 2421 2422 if (!pPerAdapterInfo || *pOutBufLen < sizeof(IP_PER_ADAPTER_INFO)) 2423 { 2424 *pOutBufLen = sizeof(IP_PER_ADAPTER_INFO); 2425 return ERROR_BUFFER_OVERFLOW; 2426 } 2427 2428 ifName = getInterfaceNameByIndex(IfIndex); 2429 if (!ifName) 2430 return ERROR_INVALID_PARAMETER; 2431 2432 MultiByteToWideChar(CP_ACP, 0, ifName, -1, &keyname[62], sizeof(keyname)/sizeof(WCHAR) - 63); 2433 HeapFree(GetProcessHeap(), 0, (LPVOID)ifName); 2434 2435 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey) != ERROR_SUCCESS) 2436 { 2437 return ERROR_NOT_SUPPORTED; 2438 } 2439 Context.NumServers = 0; 2440 Context.uSizeAvailable = *pOutBufLen; 2441 Context.uSizeRequired = sizeof(IP_PER_ADAPTER_INFO); 2442 Context.pData = pPerAdapterInfo; 2443 2444 if (*pOutBufLen >= sizeof(IP_PER_ADAPTER_INFO)) 2445 ZeroMemory(pPerAdapterInfo, sizeof(IP_PER_ADAPTER_INFO)); 2446 2447 EnumNameServers(hkey, &keyname[62], &Context, CreateNameServerListEnumNamesFunc); 2448 2449 if (Context.uSizeRequired > Context.uSizeAvailable) 2450 { 2451 *pOutBufLen = Context.uSizeRequired; 2452 RegCloseKey(hkey); 2453 return ERROR_BUFFER_OVERFLOW; 2454 } 2455 2456 if(RegQueryValueExW(hkey, L"NameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS) 2457 { 2458 pPerAdapterInfo->AutoconfigActive = FALSE; 2459 } 2460 else 2461 { 2462 pPerAdapterInfo->AutoconfigActive = TRUE; 2463 } 2464 2465 RegCloseKey(hkey); 2466 return NOERROR; 2467} 2468 2469 2470/****************************************************************** 2471 * GetRTTAndHopCount (IPHLPAPI.@) 2472 * 2473 * PARAMS 2474 * DestIpAddress [In] 2475 * HopCount [In/Out] 2476 * MaxHops [In] 2477 * RTT [In/Out] 2478 * 2479 * RETURNS 2480 * BOOL 2481 */ 2482BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT) 2483{ 2484 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n", 2485 DestIpAddress, HopCount, MaxHops, RTT); 2486 FIXME(":stub\n"); 2487 return (BOOL) 0; 2488} 2489 2490 2491/****************************************************************** 2492 * GetTcpStatisticsEx (IPHLPAPI.@) 2493 * 2494 * PARAMS 2495 * pStats [In/Out] 2496 * dwFamily [In] 2497 * 2498 * RETURNS 2499 * DWORD 2500 */ 2501DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily) 2502{ 2503 HANDLE tcpFile; 2504 DWORD ret; 2505 2506 if (!pStats) 2507 return ERROR_INVALID_PARAMETER; 2508 2509 if (dwFamily != AF_INET && dwFamily != AF_INET6) 2510 return ERROR_INVALID_PARAMETER; 2511 2512 if (!NT_SUCCESS(openTcpFile(&tcpFile, FILE_READ_DATA))) 2513 return ERROR_NOT_SUPPORTED; 2514 2515 TRACE("pStats %p\n", pStats); 2516 ret = getTCPStats(tcpFile, pStats); 2517 closeTcpFile(tcpFile); 2518 TRACE("returning %ld\n", ret); 2519 return ret; 2520} 2521 2522/****************************************************************** 2523 * GetTcpStatistics (IPHLPAPI.@) 2524 * 2525 * PARAMS 2526 * pStats [In/Out] 2527 * 2528 * RETURNS 2529 * DWORD 2530 */ 2531DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats) 2532{ 2533 return GetTcpStatisticsEx(pStats, PF_INET); 2534} 2535 2536 2537/****************************************************************** 2538 * GetTcpTable (IPHLPAPI.@) 2539 * 2540 * Get the table of active TCP connections. 2541 * 2542 * PARAMS 2543 * pTcpTable [Out] buffer for TCP connections table 2544 * pdwSize [In/Out] length of output buffer 2545 * bOrder [In] whether to order the table 2546 * 2547 * RETURNS 2548 * Success: NO_ERROR 2549 * Failure: error code from winerror.h 2550 * 2551 * NOTES 2552 * If pdwSize is less than required, the function will return 2553 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to 2554 * the required byte size. 2555 * If bOrder is true, the returned table will be sorted, first by 2556 * local address and port number, then by remote address and port 2557 * number. 2558 */ 2559DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder) 2560{ 2561 return GetExtendedTcpTable(pTcpTable, pdwSize, bOrder, AF_INET, TCP_TABLE_BASIC_ALL, 0); 2562} 2563 2564 2565/****************************************************************** 2566 * GetUdpStatisticsEx (IPHLPAPI.@) 2567 * 2568 * PARAMS 2569 * pStats [In/Out] 2570 * dwFamily [In] 2571 * 2572 * RETURNS 2573 * DWORD 2574 */ 2575DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily) 2576{ 2577 HANDLE tcpFile; 2578 DWORD ret; 2579 2580 if (!pStats) 2581 return ERROR_INVALID_PARAMETER; 2582 2583 if (dwFamily != AF_INET && dwFamily != AF_INET6) 2584 return ERROR_INVALID_PARAMETER; 2585 2586 if (!NT_SUCCESS(openTcpFile(&tcpFile, FILE_READ_DATA))) 2587 return ERROR_NOT_SUPPORTED; 2588 2589 TRACE("pStats %p\n", pStats); 2590 ret = getUDPStats(tcpFile, pStats); 2591 closeTcpFile(tcpFile); 2592 TRACE("returning %ld\n", ret); 2593 return ret; 2594} 2595 2596/****************************************************************** 2597 * GetUdpStatistics (IPHLPAPI.@) 2598 * 2599 * PARAMS 2600 * pStats [In/Out] 2601 * 2602 * RETURNS 2603 * DWORD 2604 */ 2605DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats) 2606{ 2607 return GetUdpStatisticsEx(pStats, PF_INET); 2608} 2609 2610 2611/****************************************************************** 2612 * GetUdpTable (IPHLPAPI.@) 2613 * 2614 * PARAMS 2615 * pUdpTable [In/Out] 2616 * pdwSize [In/Out] 2617 * bOrder [In] 2618 * 2619 * RETURNS 2620 * DWORD 2621 */ 2622DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder) 2623{ 2624 return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, AF_INET, UDP_TABLE_BASIC, 0); 2625} 2626 2627 2628/****************************************************************** 2629 * GetUniDirectionalAdapterInfo (IPHLPAPI.@) 2630 * 2631 * This is a Win98-only function to get information on "unidirectional" 2632 * adapters. Since this is pretty nonsensical in other contexts, it 2633 * never returns anything. 2634 * 2635 * PARAMS 2636 * pIPIfInfo [Out] buffer for adapter infos 2637 * dwOutBufLen [Out] length of the output buffer 2638 * 2639 * RETURNS 2640 * Success: NO_ERROR 2641 * Failure: error code from winerror.h 2642 * 2643 * FIXME 2644 * Stub, returns ERROR_NOT_SUPPORTED. 2645 */ 2646DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen) 2647{ 2648 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen); 2649 /* a unidirectional adapter?? not bloody likely! */ 2650 return ERROR_NOT_SUPPORTED; 2651} 2652 2653 2654/****************************************************************** 2655 * IpReleaseAddress (IPHLPAPI.@) 2656 * 2657 * Release an IP obtained through DHCP, 2658 * 2659 * PARAMS 2660 * AdapterInfo [In] adapter to release IP address 2661 * 2662 * RETURNS 2663 * Success: NO_ERROR 2664 * Failure: error code from winerror.h 2665 */ 2666DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) 2667{ 2668 DWORD Status, Version = 0; 2669 2670 if (!AdapterInfo) 2671 return ERROR_INVALID_PARAMETER; 2672 2673 /* Maybe we should do this in DllMain */ 2674 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS) 2675 return ERROR_PROC_NOT_FOUND; 2676 2677 Status = DhcpReleaseParameters(AdapterInfo->Name); 2678 2679 DhcpCApiCleanup(); 2680 2681 return Status; 2682} 2683 2684 2685/****************************************************************** 2686 * IpRenewAddress (IPHLPAPI.@) 2687 * 2688 * Renew an IP obtained through DHCP. 2689 * 2690 * PARAMS 2691 * AdapterInfo [In] adapter to renew IP address 2692 * 2693 * RETURNS 2694 * Success: NO_ERROR 2695 * Failure: error code from winerror.h 2696 */ 2697DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) 2698{ 2699 DWORD Status, Version = 0; 2700 2701 if (!AdapterInfo) 2702 return ERROR_INVALID_PARAMETER; 2703 2704 /* Maybe we should do this in DllMain */ 2705 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS) 2706 return ERROR_PROC_NOT_FOUND; 2707 2708 Status = DhcpAcquireParameters(AdapterInfo->Name); 2709 2710 DhcpCApiCleanup(); 2711 2712 return Status; 2713} 2714 2715 2716/****************************************************************** 2717 * NotifyAddrChange (IPHLPAPI.@) 2718 * 2719 * Notify caller whenever the ip-interface map is changed. 2720 * 2721 * PARAMS 2722 * Handle [Out] handle usable in asynchronous notification 2723 * overlapped [In] overlapped structure that notifies the caller 2724 * 2725 * RETURNS 2726 * Success: NO_ERROR 2727 * Failure: error code from winerror.h 2728 * 2729 * FIXME 2730 * Stub, returns ERROR_NOT_SUPPORTED. 2731 */ 2732DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped) 2733{ 2734 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped); 2735 if (Handle) *Handle = INVALID_HANDLE_VALUE; 2736 if (overlapped) ((IO_STATUS_BLOCK *) overlapped)->Status = STATUS_PENDING; 2737 return ERROR_IO_PENDING; 2738} 2739 2740 2741/****************************************************************** 2742 * NotifyRouteChange (IPHLPAPI.@) 2743 * 2744 * Notify caller whenever the ip routing table is changed. 2745 * 2746 * PARAMS 2747 * Handle [Out] handle usable in asynchronous notification 2748 * overlapped [In] overlapped structure that notifies the caller 2749 * 2750 * RETURNS 2751 * Success: NO_ERROR 2752 * Failure: error code from winerror.h 2753 * 2754 * FIXME 2755 * Stub, returns ERROR_NOT_SUPPORTED. 2756 */ 2757DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped) 2758{ 2759 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped); 2760 return ERROR_NOT_SUPPORTED; 2761} 2762 2763/****************************************************************** 2764 * SendARP (IPHLPAPI.@) 2765 * 2766 * Send an ARP request. 2767 * 2768 * PARAMS 2769 * DestIP [In] attempt to obtain this IP 2770 * SrcIP [In] optional sender IP address 2771 * pMacAddr [Out] buffer for the mac address 2772 * PhyAddrLen [In/Out] length of the output buffer 2773 * 2774 * RETURNS 2775 * Success: NO_ERROR 2776 * Failure: error code from winerror.h 2777 */ 2778DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen) 2779{ 2780 IPAddr IPs[2]; 2781 ULONG Size; 2782 2783 if (IsBadWritePtr(pMacAddr, sizeof(ULONG)) || IsBadWritePtr(PhyAddrLen, sizeof(ULONG))) 2784 return ERROR_INVALID_PARAMETER; 2785 2786 IPs[0] = DestIP; 2787 IPs[1] = SrcIP; 2788 Size = sizeof(IPs); 2789 return TCPSendIoctl(INVALID_HANDLE_VALUE, IOCTL_QUERY_IP_HW_ADDRESS, IPs, &Size, pMacAddr, PhyAddrLen); 2790} 2791 2792 2793/****************************************************************** 2794 * SetIfEntry (IPHLPAPI.@) 2795 * 2796 * Set the administrative status of an interface. 2797 * 2798 * PARAMS 2799 * pIfRow [In] dwAdminStatus member specifies the new status. 2800 * 2801 * RETURNS 2802 * Success: NO_ERROR 2803 * Failure: error code from winerror.h 2804 * 2805 * FIXME 2806 * Stub, returns ERROR_NOT_SUPPORTED. 2807 */ 2808DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow) 2809{ 2810 FIXME("(pIfRow %p): stub\n", pIfRow); 2811 /* this is supposed to set an interface administratively up or down. 2812 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and 2813 this sort of down is indistinguishable from other sorts of down (e.g. no 2814 link). */ 2815 return ERROR_NOT_SUPPORTED; 2816} 2817 2818 2819/****************************************************************** 2820 * SetIpForwardEntry (IPHLPAPI.@) 2821 * 2822 * Modify an existing route. 2823 * 2824 * PARAMS 2825 * pRoute [In] route with the new information 2826 * 2827 * RETURNS 2828 * Success: NO_ERROR 2829 * Failure: error code from winerror.h 2830 */ 2831DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute) 2832{ 2833 return setIpForwardEntry( pRoute ); 2834} 2835 2836 2837/****************************************************************** 2838 * SetIpNetEntry (IPHLPAPI.@) 2839 * 2840 * Modify an existing ARP entry. 2841 * 2842 * PARAMS 2843 * pArpEntry [In] ARP entry with the new information 2844 * 2845 * RETURNS 2846 * Success: NO_ERROR 2847 * Failure: error code from winerror.h 2848 */ 2849DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry) 2850{ 2851 HANDLE tcpFile; 2852 NTSTATUS status; 2853 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req = 2854 TCP_REQUEST_SET_INFORMATION_INIT; 2855 TDIEntityID id; 2856 DWORD returnSize; 2857 PMIB_IPNETROW arpBuff; 2858 2859 if (!pArpEntry) 2860 return ERROR_INVALID_PARAMETER; 2861 2862 if (!NT_SUCCESS(openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ))) 2863 return ERROR_NOT_SUPPORTED; 2864 2865 if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id ))) 2866 { 2867 closeTcpFile(tcpFile); 2868 return ERROR_INVALID_PARAMETER; 2869 } 2870 2871 req.Req.ID.toi_class = INFO_CLASS_PROTOCOL; 2872 req.Req.ID.toi_type = INFO_TYPE_PROVIDER; 2873 req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID; 2874 req.Req.ID.toi_entity.tei_instance = id.tei_instance; 2875 req.Req.ID.toi_entity.tei_entity = AT_ENTITY; 2876 req.Req.BufferSize = sizeof(MIB_IPNETROW); 2877 arpBuff = (PMIB_IPNETROW)&req.Req.Buffer[0]; 2878 2879 RtlCopyMemory(arpBuff, pArpEntry, sizeof(MIB_IPNETROW)); 2880 2881 status = DeviceIoControl( tcpFile, 2882 IOCTL_TCP_SET_INFORMATION_EX, 2883 &req, 2884 sizeof(req), 2885 NULL, 2886 0, 2887 &returnSize, 2888 NULL ); 2889 2890 closeTcpFile(tcpFile); 2891 2892 if (status) 2893 return NO_ERROR; 2894 else 2895 return ERROR_INVALID_PARAMETER; 2896} 2897 2898 2899/****************************************************************** 2900 * SetIpStatistics (IPHLPAPI.@) 2901 * 2902 * Toggle IP forwarding and det the default TTL value. 2903 * 2904 * PARAMS 2905 * pIpStats [In] IP statistics with the new information 2906 * 2907 * RETURNS 2908 * Success: NO_ERROR 2909 * Failure: error code from winerror.h 2910 * 2911 * FIXME 2912 * Stub, returns NO_ERROR. 2913 */ 2914DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats) 2915{ 2916 FIXME("(pIpStats %p): stub\n", pIpStats); 2917 return 0; 2918} 2919 2920 2921/****************************************************************** 2922 * SetIpTTL (IPHLPAPI.@) 2923 * 2924 * Set the default TTL value. 2925 * 2926 * PARAMS 2927 * nTTL [In] new TTL value 2928 * 2929 * RETURNS 2930 * Success: NO_ERROR 2931 * Failure: error code from winerror.h 2932 * 2933 * FIXME 2934 * Stub, returns NO_ERROR. 2935 */ 2936DWORD WINAPI SetIpTTL(UINT nTTL) 2937{ 2938 FIXME("(nTTL %d): stub\n", nTTL); 2939 return 0; 2940} 2941 2942 2943/****************************************************************** 2944 * SetTcpEntry (IPHLPAPI.@) 2945 * 2946 * Set the state of a TCP connection. 2947 * 2948 * PARAMS 2949 * pTcpRow [In] specifies connection with new state 2950 * 2951 * RETURNS 2952 * Success: NO_ERROR 2953 * Failure: error code from winerror.h 2954 * 2955 * FIXME 2956 * Stub, returns NO_ERROR. 2957 */ 2958DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow) 2959{ 2960 FIXME("(pTcpRow %p): stub\n", pTcpRow); 2961 return 0; 2962} 2963 2964 2965/****************************************************************** 2966 * UnenableRouter (IPHLPAPI.@) 2967 * 2968 * Decrement the IP-forwarding reference count. Turn off IP-forwarding 2969 * if it reaches zero. 2970 * 2971 * PARAMS 2972 * pOverlapped [In/Out] should be the same as in EnableRouter() 2973 * lpdwEnableCount [Out] optional, receives reference count 2974 * 2975 * RETURNS 2976 * Success: NO_ERROR 2977 * Failure: error code from winerror.h 2978 * 2979 * FIXME 2980 * Stub, returns ERROR_NOT_SUPPORTED. 2981 */ 2982DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount) 2983{ 2984 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped, 2985 lpdwEnableCount); 2986 return ERROR_NOT_SUPPORTED; 2987} 2988 2989/* 2990 * @unimplemented 2991 */ 2992DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size) 2993{ 2994 FIXME(":stub\n"); 2995 return 0L; 2996} 2997 2998 2999/* 3000 * @unimplemented 3001 */ 3002PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID) 3003{ 3004 FIXME(":stub\n"); 3005 return 0L; 3006} 3007 3008#ifdef GetAdaptersAddressesV1 3009DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen) 3010{ 3011 InterfaceIndexTable *indexTable; 3012 IFInfo ifInfo; 3013 int i; 3014 ULONG ret, requiredSize = 0; 3015 PIP_ADAPTER_ADDRESSES currentAddress; 3016 PUCHAR currentLocation; 3017 HANDLE tcpFile; 3018 3019 if (!pOutBufLen) return ERROR_INVALID_PARAMETER; 3020 if (Reserved) return ERROR_INVALID_PARAMETER; 3021 3022 indexTable = getInterfaceIndexTable(); 3023 if (!indexTable) 3024 return ERROR_NOT_ENOUGH_MEMORY; 3025 3026 ret = openTcpFile(&tcpFile, FILE_READ_DATA); 3027 if (!NT_SUCCESS(ret)) 3028 { 3029 free(indexTable); 3030 return ERROR_NO_DATA; 3031 } 3032 3033 for (i = indexTable->numIndexes; i >= 0; i--) 3034 { 3035 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, 3036 NULL, 3037 indexTable->indexes[i], 3038 &ifInfo))) 3039 { 3040 /* The whole struct */ 3041 requiredSize += sizeof(IP_ADAPTER_ADDRESSES); 3042 3043 /* Friendly name */ 3044 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) 3045 requiredSize += ifInfo.if_info.ent.if_descrlen + 1; //FIXME 3046 3047 /* Adapter name */ 3048 requiredSize += ifInfo.if_info.ent.if_descrlen + 1; 3049 3050 /* Unicast address */ 3051 if (!(Flags & GAA_FLAG_SKIP_UNICAST)) 3052 requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS); 3053 3054 /* FIXME: Implement multicast, anycast, and dns server stuff */ 3055 3056 /* FIXME: Implement dns suffix and description */ 3057 requiredSize += 2 * sizeof(WCHAR); 3058 3059 /* We're only going to implement what's required for XP SP0 */ 3060 } 3061 } 3062 TRACE("size: %d, requiredSize: %d\n", *pOutBufLen, requiredSize); 3063 if (!pAdapterAddresses || *pOutBufLen < requiredSize) 3064 { 3065 *pOutBufLen = requiredSize; 3066 closeTcpFile(tcpFile); 3067 free(indexTable); 3068 return ERROR_BUFFER_OVERFLOW; 3069 } 3070 3071 RtlZeroMemory(pAdapterAddresses, requiredSize); 3072 3073 /* Let's set up the pointers */ 3074 currentAddress = pAdapterAddresses; 3075 for (i = indexTable->numIndexes; i >= 0; i--) 3076 { 3077 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, 3078 NULL, 3079 indexTable->indexes[i], 3080 &ifInfo))) 3081 { 3082 currentLocation = (PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES); 3083 3084 /* FIXME: Friendly name */ 3085 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) 3086 { 3087 currentAddress->FriendlyName = (PVOID)currentLocation; 3088 currentLocation += sizeof(WCHAR); 3089 } 3090 3091 /* Adapter name */ 3092 currentAddress->AdapterName = (PVOID)currentLocation; 3093 currentLocation += ifInfo.if_info.ent.if_descrlen + 1; 3094 3095 /* Unicast address */ 3096 if (!(Flags & GAA_FLAG_SKIP_UNICAST)) 3097 { 3098 currentAddress->FirstUnicastAddress = (PVOID)currentLocation; 3099 currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS); 3100 currentAddress->FirstUnicastAddress->Address.lpSockaddr = (PVOID)currentLocation; 3101 currentLocation += sizeof(struct sockaddr); 3102 } 3103 3104 /* FIXME: Implement multicast, anycast, and dns server stuff */ 3105 3106 /* FIXME: Implement dns suffix and description */ 3107 currentAddress->DnsSuffix = (PVOID)currentLocation; 3108 currentLocation += sizeof(WCHAR); 3109 3110 currentAddress->Description = (PVOID)currentLocation; 3111 currentLocation += sizeof(WCHAR); 3112 3113 currentAddress->Next = (PVOID)currentLocation; 3114 /* Terminate the last address correctly */ 3115 if(i==0) 3116 currentAddress->Next = NULL; 3117 3118 /* We're only going to implement what's required for XP SP0 */ 3119 3120 currentAddress = currentAddress->Next; 3121 } 3122 } 3123 3124 /* Now again, for real this time */ 3125 3126 currentAddress = pAdapterAddresses; 3127 for (i = indexTable->numIndexes; i >= 0; i--) 3128 { 3129 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, 3130 NULL, 3131 indexTable->indexes[i], 3132 &ifInfo))) 3133 { 3134 /* Make sure we're not looping more than we hoped for */ 3135 ASSERT(currentAddress); 3136 3137 /* Alignment information */ 3138 currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES); 3139 currentAddress->IfIndex = indexTable->indexes[i]; 3140 3141 /* Adapter name */ 3142 memcpy(currentAddress->AdapterName, ifInfo.if_info.ent.if_descr, ifInfo.if_info.ent.if_descrlen); 3143 currentAddress->AdapterName[ifInfo.if_info.ent.if_descrlen] = '\0'; 3144 3145 if (!(Flags & GAA_FLAG_SKIP_UNICAST)) 3146 { 3147 currentAddress->FirstUnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS); 3148 currentAddress->FirstUnicastAddress->Flags = 0; //FIXME 3149 currentAddress->FirstUnicastAddress->Next = NULL; //FIXME: Support more than one address per adapter 3150 currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family = AF_INET; 3151 memcpy(currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data, 3152 &ifInfo.ip_addr.iae_addr, 3153 sizeof(ifInfo.ip_addr.iae_addr)); 3154 currentAddress->FirstUnicastAddress->Address.iSockaddrLength = sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT); 3155 currentAddress->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther; //FIXME 3156 currentAddress->FirstUnicastAddress->SuffixOrigin = IpPrefixOriginOther; //FIXME 3157 currentAddress->FirstUnicastAddress->DadState = IpDadStatePreferred; //FIXME 3158 currentAddress->FirstUnicastAddress->ValidLifetime = 0xFFFFFFFF; //FIXME 3159 currentAddress->FirstUnicastAddress->PreferredLifetime = 0xFFFFFFFF; //FIXME 3160 currentAddress->FirstUnicastAddress->LeaseLifetime = 0xFFFFFFFF; //FIXME 3161 } 3162 3163 /* FIXME: Implement multicast, anycast, and dns server stuff */ 3164 currentAddress->FirstAnycastAddress = NULL; 3165 currentAddress->FirstMulticastAddress = NULL; 3166 currentAddress->FirstDnsServerAddress = NULL; 3167 3168 /* FIXME: Implement dns suffix, description, and friendly name */ 3169 currentAddress->DnsSuffix[0] = UNICODE_NULL; 3170 currentAddress->Description[0] = UNICODE_NULL; 3171 currentAddress->FriendlyName[0] = UNICODE_NULL; 3172 3173 /* Physical Address */ 3174 memcpy(currentAddress->PhysicalAddress, ifInfo.if_info.ent.if_physaddr, ifInfo.if_info.ent.if_physaddrlen); 3175 currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen; 3176 3177 /* Flags */ 3178 currentAddress->Flags = 0; //FIXME 3179 3180 /* MTU */ 3181 currentAddress->Mtu = ifInfo.if_info.ent.if_mtu; 3182 3183 /* Interface type */ 3184 currentAddress->IfType = ifInfo.if_info.ent.if_type; 3185 3186 /* Operational status */ 3187 if(ifInfo.if_info.ent.if_operstatus >= IF_OPER_STATUS_CONNECTING) 3188 currentAddress->OperStatus = IfOperStatusUp; 3189 else 3190 currentAddress->OperStatus = IfOperStatusDown; 3191 3192 /* We're only going to implement what's required for XP SP0 */ 3193 3194 /* Move to the next address */ 3195 currentAddress = currentAddress->Next; 3196 } 3197 } 3198 3199 closeTcpFile(tcpFile); 3200 free(indexTable); 3201 3202 return NO_ERROR; 3203} 3204#endif 3205 3206/* 3207 * @unimplemented 3208 */ 3209BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped) 3210{ 3211 FIXME(":stub\n"); 3212 return 0L; 3213} 3214 3215/* 3216 * @unimplemented 3217 */ 3218DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex) 3219{ 3220 FIXME(":stub\n"); 3221 return 0L; 3222} 3223 3224#ifdef GetAdaptersAddressesV1 3225/* 3226 * @unimplemented 3227 */ 3228DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags) 3229{ 3230 FIXME(":stub\n"); 3231 return 0L; 3232} 3233#endif 3234 3235/* 3236 * @unimplemented 3237 */ 3238DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily) 3239{ 3240 FIXME(":stub\n"); 3241 3242 if (!pStats) 3243 return ERROR_INVALID_PARAMETER; 3244 3245 if (dwFamily != AF_INET && dwFamily != AF_INET6) 3246 return ERROR_INVALID_PARAMETER; 3247 3248 return 0L; 3249} 3250 3251DWORD WINAPI 3252SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute) 3253{ 3254 FIXME("SetIpForwardEntryToStack() stub\n"); 3255 return 0L; 3256} 3257 3258DWORD GetInterfaceNameInternal(_In_ const GUID * pInterfaceGUID, 3259 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName, 3260 _Inout_ PULONG pOutBufLen) 3261{ 3262 UNICODE_STRING GuidString; 3263 DWORD result, type; 3264 WCHAR szKeyName[2*MAX_PATH]; 3265 HRESULT hr; 3266 HKEY hKey; 3267 3268 if (pInterfaceGUID == NULL || pOutBufLen == NULL) 3269 return ERROR_INVALID_PARAMETER; 3270 3271 result = RtlStringFromGUID(pInterfaceGUID, &GuidString); 3272 3273 if (!NT_SUCCESS(result)) 3274 { 3275 // failed to convert guid to string 3276 return RtlNtStatusToDosError(result); 3277 } 3278 3279 hr = StringCbPrintfW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", GuidString.Buffer); 3280 RtlFreeUnicodeString(&GuidString); 3281 3282 if (FAILED(hr)) 3283 { 3284 // key name is too long 3285 return ERROR_BUFFER_OVERFLOW; 3286 } 3287 3288 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKey); 3289 3290 if (result != ERROR_SUCCESS) 3291 { 3292 // failed to find adapter entry 3293 return ERROR_NOT_FOUND; 3294 } 3295 3296 result = RegQueryValueExW(hKey, L"Name", NULL, &type, (PVOID)pInterfaceName, pOutBufLen); 3297 3298 RegCloseKey(hKey); 3299 3300 if (result == ERROR_MORE_DATA) 3301 { 3302 *pOutBufLen = MAX_INTERFACE_NAME_LEN * 2; 3303 return ERROR_INSUFFICIENT_BUFFER; 3304 } 3305 3306 if (result != ERROR_SUCCESS || type != REG_SZ) 3307 { 3308 // failed to read adapter name 3309 return ERROR_NO_DATA; 3310 } 3311 return ERROR_SUCCESS; 3312} 3313 3314DWORD WINAPI 3315NhGetInterfaceNameFromDeviceGuid(_In_ const GUID * pInterfaceGUID, 3316 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName, 3317 _Inout_ PULONG pOutBufLen, 3318 DWORD dwUnknown4, 3319 DWORD dwUnknown5) 3320{ 3321 SetLastError(ERROR_SUCCESS); 3322 3323 if (pInterfaceName == NULL) 3324 return ERROR_INVALID_PARAMETER; 3325 3326 return GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen); 3327} 3328 3329DWORD WINAPI 3330NhGetInterfaceNameFromGuid(_In_ const GUID * pInterfaceGUID, 3331 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName, 3332 _Inout_ PULONG pOutBufLen, 3333 DWORD dwUnknown4, 3334 DWORD dwUnknown5) 3335{ 3336 DWORD result; 3337 3338 result = GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen); 3339 3340 if (result == ERROR_NOT_FOUND) 3341 SetLastError(ERROR_PATH_NOT_FOUND); 3342 3343 return result; 3344}