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