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