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, matchedBits, matchedNdx = 0; 771 772 for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) { 773 if ((dwDestAddr & table->table[ndx].dwForwardMask) == 774 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) { 775 DWORD numShifts, mask; 776 777 for (numShifts = 0, mask = table->table[ndx].dwForwardMask; 778 mask && !(mask & 1); mask >>= 1, numShifts++) 779 ; 780 if (numShifts > matchedBits) { 781 matchedBits = numShifts; 782 matchedNdx = ndx; 783 } 784 } 785 } 786 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW)); 787 HeapFree(GetProcessHeap(), 0, table); 788 ret = ERROR_SUCCESS; 789 } 790 else 791 ret = ERROR_OUTOFMEMORY; 792 TRACE("returning %ld\n", ret); 793 return ret; 794 } 795 796 /****************************************************************** 797 * GetExtendedTcpTable (IPHLPAPI.@) 798 * 799 * Get the table of TCP endpoints available to the application. 800 * 801 * PARAMS 802 * pTcpTable [Out] table struct with the filtered TCP endpoints available to application 803 * pdwSize [In/Out] estimated size of the structure returned in pTcpTable, in bytes 804 * bOrder [In] whether to order the table 805 * ulAf [in] version of IP used by the TCP endpoints 806 * TableClass [in] type of the TCP table structure from TCP_TABLE_CLASS 807 * Reserved [in] reserved - this value must be zero 808 * 809 * RETURNS 810 * Success: NO_ERROR 811 * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER 812 * 813 * NOTES 814 */ 815 816 DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved) 817 { 818 DWORD ret = NO_ERROR; 819 820 if (TableClass == TCP_TABLE_OWNER_PID_ALL) { 821 if (*pdwSize == 0) { 822 *pdwSize = sizeof(MIB_TCPTABLE_OWNER_PID); 823 return ERROR_INSUFFICIENT_BUFFER; 824 } else { 825 ZeroMemory(pTcpTable, sizeof(MIB_TCPTABLE_OWNER_PID)); 826 return NO_ERROR; 827 } 828 } 829 830 831 UNIMPLEMENTED; 832 return ret; 833 } 834 835 836 /****************************************************************** 837 * GetFriendlyIfIndex (IPHLPAPI.@) 838 * 839 * 840 * PARAMS 841 * 842 * IfIndex [In] 843 * 844 * RETURNS 845 * 846 * DWORD 847 * 848 */ 849 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex) 850 { 851 /* windows doesn't validate these, either, just makes sure the top byte is 852 cleared. I assume my ifenum module never gives an index with the top 853 byte set. */ 854 TRACE("returning %ld\n", IfIndex); 855 return IfIndex; 856 } 857 858 859 /****************************************************************** 860 * GetIcmpStatistics (IPHLPAPI.@) 861 * 862 * 863 * PARAMS 864 * 865 * pStats [In/Out] 866 * 867 * RETURNS 868 * 869 * DWORD 870 * 871 */ 872 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats) 873 { 874 DWORD ret; 875 876 TRACE("pStats %p\n", pStats); 877 ret = getICMPStats(pStats); 878 TRACE("returning %ld\n", ret); 879 return ret; 880 } 881 882 883 /****************************************************************** 884 * GetIfEntry (IPHLPAPI.@) 885 * 886 * 887 * PARAMS 888 * 889 * pIfRow [In/Out] 890 * 891 * RETURNS 892 * 893 * DWORD 894 * 895 */ 896 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow) 897 { 898 DWORD ret; 899 const char *name; 900 901 TRACE("pIfRow %p\n", pIfRow); 902 if (!pIfRow) 903 return ERROR_INVALID_PARAMETER; 904 905 name = getInterfaceNameByIndex(pIfRow->dwIndex); 906 if (name) { 907 ret = getInterfaceEntryByIndex(pIfRow->dwIndex, pIfRow); 908 if (ret == NO_ERROR) 909 ret = getInterfaceStatsByName(name, pIfRow); 910 consumeInterfaceName(name); 911 } 912 else 913 ret = ERROR_INVALID_DATA; 914 TRACE("returning %ld\n", ret); 915 return ret; 916 } 917 918 919 static int IfTableSorter(const void *a, const void *b) 920 { 921 int ret; 922 923 if (a && b) 924 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex; 925 else 926 ret = 0; 927 return ret; 928 } 929 930 931 /****************************************************************** 932 * GetIfTable (IPHLPAPI.@) 933 * 934 * 935 * PARAMS 936 * 937 * pIfTable [In/Out] 938 * pdwSize [In/Out] 939 * bOrder [In] 940 * 941 * RETURNS 942 * 943 * DWORD 944 * 945 */ 946 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) 947 { 948 DWORD ret; 949 950 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize, 951 (DWORD)bOrder); 952 if (!pdwSize) 953 ret = ERROR_INVALID_PARAMETER; 954 else { 955 DWORD numInterfaces = getNumInterfaces(); 956 ULONG size; 957 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces); 958 size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW); 959 960 if (!pIfTable || *pdwSize < size) { 961 *pdwSize = size; 962 ret = ERROR_INSUFFICIENT_BUFFER; 963 } 964 else { 965 InterfaceIndexTable *table = getInterfaceIndexTable(); 966 967 if (table) { 968 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) * 969 sizeof(MIB_IFROW); 970 if (*pdwSize < size) { 971 *pdwSize = size; 972 ret = ERROR_INSUFFICIENT_BUFFER; 973 } 974 else { 975 DWORD ndx; 976 977 pIfTable->dwNumEntries = 0; 978 for (ndx = 0; ndx < table->numIndexes; ndx++) { 979 pIfTable->table[ndx].dwIndex = table->indexes[ndx]; 980 GetIfEntry(&pIfTable->table[ndx]); 981 pIfTable->dwNumEntries++; 982 } 983 if (bOrder) 984 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW), 985 IfTableSorter); 986 ret = NO_ERROR; 987 } 988 free(table); 989 } 990 else 991 ret = ERROR_OUTOFMEMORY; 992 } 993 } 994 TRACE("returning %ld\n", ret); 995 return ret; 996 } 997 998 999 /****************************************************************** 1000 * GetInterfaceInfo (IPHLPAPI.@) 1001 * 1002 * 1003 * PARAMS 1004 * 1005 * pIfTable [In/Out] 1006 * dwOutBufLen [In/Out] 1007 * 1008 * RETURNS 1009 * 1010 * DWORD 1011 * 1012 */ 1013 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen) 1014 { 1015 DWORD ret; 1016 1017 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen); 1018 if (!dwOutBufLen) 1019 ret = ERROR_INVALID_PARAMETER; 1020 else { 1021 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces(); 1022 ULONG size; 1023 TRACE("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces); 1024 size = sizeof(IP_INTERFACE_INFO) + (numNonLoopbackInterfaces) * 1025 sizeof(IP_ADAPTER_INDEX_MAP); 1026 1027 if (!pIfTable || *dwOutBufLen < size) { 1028 *dwOutBufLen = size; 1029 ret = ERROR_INSUFFICIENT_BUFFER; 1030 } 1031 else { 1032 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable(); 1033 1034 if (table) { 1035 TRACE("table->numIndexes == 0x%x\n", table->numIndexes); 1036 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes) * 1037 sizeof(IP_ADAPTER_INDEX_MAP); 1038 if (*dwOutBufLen < size) { 1039 *dwOutBufLen = size; 1040 ret = ERROR_INSUFFICIENT_BUFFER; 1041 } 1042 else { 1043 DWORD ndx; 1044 1045 pIfTable->NumAdapters = 0; 1046 for (ndx = 0; ndx < table->numIndexes; ndx++) { 1047 const char *walker, *name; 1048 WCHAR *assigner; 1049 1050 pIfTable->Adapter[ndx].Index = table->indexes[ndx]; 1051 name = getInterfaceNameByIndex(table->indexes[ndx]); 1052 for (walker = name, assigner = pIfTable->Adapter[ndx].Name; 1053 walker && *walker && 1054 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1; 1055 walker++, assigner++) 1056 *assigner = *walker; 1057 *assigner = 0; 1058 consumeInterfaceName(name); 1059 pIfTable->NumAdapters++; 1060 } 1061 ret = NO_ERROR; 1062 } 1063 free(table); 1064 } 1065 else 1066 ret = ERROR_OUTOFMEMORY; 1067 } 1068 } 1069 TRACE("returning %ld\n", ret); 1070 return ret; 1071 } 1072 1073 1074 static int IpAddrTableSorter(const void *a, const void *b) 1075 { 1076 int ret; 1077 1078 if (a && b) 1079 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr; 1080 else 1081 ret = 0; 1082 return ret; 1083 } 1084 1085 1086 /****************************************************************** 1087 * GetIpAddrTable (IPHLPAPI.@) 1088 * 1089 * 1090 * PARAMS 1091 * 1092 * pIpAddrTable [In/Out] 1093 * pdwSize [In/Out] 1094 * bOrder [In] 1095 * 1096 * RETURNS 1097 * 1098 * DWORD 1099 * 1100 */ 1101 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder) 1102 { 1103 DWORD ret; 1104 1105 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize, 1106 (DWORD)bOrder); 1107 if (!pdwSize) 1108 ret = ERROR_INVALID_PARAMETER; 1109 else { 1110 DWORD numInterfaces = getNumInterfaces(); 1111 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) * 1112 sizeof(MIB_IPADDRROW); 1113 1114 if (!pIpAddrTable || *pdwSize < size) { 1115 *pdwSize = size; 1116 ret = ERROR_INSUFFICIENT_BUFFER; 1117 } 1118 else { 1119 InterfaceIndexTable *table = getInterfaceIndexTable(); 1120 1121 if (table) { 1122 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) * 1123 sizeof(MIB_IPADDRROW); 1124 if (*pdwSize < size) { 1125 *pdwSize = size; 1126 ret = ERROR_INSUFFICIENT_BUFFER; 1127 } 1128 else { 1129 DWORD ndx, bcast; 1130 1131 pIpAddrTable->dwNumEntries = 0; 1132 for (ndx = 0; ndx < table->numIndexes; ndx++) { 1133 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx]; 1134 pIpAddrTable->table[ndx].dwAddr = 1135 getInterfaceIPAddrByIndex(table->indexes[ndx]); 1136 pIpAddrTable->table[ndx].dwMask = 1137 getInterfaceMaskByIndex(table->indexes[ndx]); 1138 /* the dwBCastAddr member isn't the broadcast address, it indicates 1139 * whether the interface uses the 1's broadcast address (1) or the 1140 * 0's broadcast address (0). 1141 */ 1142 bcast = getInterfaceBCastAddrByIndex(table->indexes[ndx]); 1143 pIpAddrTable->table[ndx].dwBCastAddr = 1144 (bcast & pIpAddrTable->table[ndx].dwMask) ? 1 : 0; 1145 /* FIXME: hardcoded reasm size, not sure where to get it */ 1146 pIpAddrTable->table[ndx].dwReasmSize = 65535; 1147 pIpAddrTable->table[ndx].unused1 = 0; 1148 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */ 1149 pIpAddrTable->dwNumEntries++; 1150 } 1151 if (bOrder) 1152 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries, 1153 sizeof(MIB_IPADDRROW), IpAddrTableSorter); 1154 ret = NO_ERROR; 1155 } 1156 free(table); 1157 } 1158 else 1159 ret = ERROR_OUTOFMEMORY; 1160 } 1161 } 1162 TRACE("returning %ld\n", ret); 1163 return ret; 1164 } 1165 1166 1167 static int IpForwardTableSorter(const void *a, const void *b) 1168 { 1169 int ret; 1170 1171 if (a && b) { 1172 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b; 1173 1174 ret = rowA->dwForwardDest - rowB->dwForwardDest; 1175 if (ret == 0) { 1176 ret = rowA->dwForwardProto - rowB->dwForwardProto; 1177 if (ret == 0) { 1178 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy; 1179 if (ret == 0) 1180 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop; 1181 } 1182 } 1183 } 1184 else 1185 ret = 0; 1186 return ret; 1187 } 1188 1189 1190 /****************************************************************** 1191 * GetIpForwardTable (IPHLPAPI.@) 1192 * 1193 * 1194 * PARAMS 1195 * 1196 * pIpForwardTable [In/Out] 1197 * pdwSize [In/Out] 1198 * bOrder [In] 1199 * 1200 * RETURNS 1201 * 1202 * DWORD 1203 * 1204 */ 1205 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder) 1206 { 1207 DWORD ret; 1208 1209 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable, 1210 pdwSize, (DWORD)bOrder); 1211 if (!pdwSize) 1212 ret = ERROR_INVALID_PARAMETER; 1213 else { 1214 DWORD numRoutes = getNumRoutes(); 1215 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * 1216 sizeof(MIB_IPFORWARDROW); 1217 1218 if (!pIpForwardTable || *pdwSize < sizeNeeded) { 1219 *pdwSize = sizeNeeded; 1220 ret = ERROR_INSUFFICIENT_BUFFER; 1221 } 1222 else { 1223 RouteTable *table = getRouteTable(); 1224 if (table) { 1225 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) * 1226 sizeof(MIB_IPFORWARDROW); 1227 if (*pdwSize < sizeNeeded) { 1228 *pdwSize = sizeNeeded; 1229 ret = ERROR_INSUFFICIENT_BUFFER; 1230 } 1231 else { 1232 DWORD ndx; 1233 1234 pIpForwardTable->dwNumEntries = table->numRoutes; 1235 for (ndx = 0; ndx < numRoutes; ndx++) { 1236 pIpForwardTable->table[ndx].dwForwardIfIndex = 1237 table->routes[ndx].ifIndex; 1238 pIpForwardTable->table[ndx].dwForwardDest = 1239 table->routes[ndx].dest; 1240 pIpForwardTable->table[ndx].dwForwardMask = 1241 table->routes[ndx].mask; 1242 pIpForwardTable->table[ndx].dwForwardPolicy = 0; 1243 pIpForwardTable->table[ndx].dwForwardNextHop = 1244 table->routes[ndx].gateway; 1245 /* FIXME: this type is appropriate for local interfaces; may not 1246 always be appropriate */ 1247 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT; 1248 /* FIXME: other protos might be appropriate, e.g. the default route 1249 is typically set with MIB_IPPROTO_NETMGMT instead */ 1250 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL; 1251 /* punt on age and AS */ 1252 pIpForwardTable->table[ndx].dwForwardAge = 0; 1253 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0; 1254 pIpForwardTable->table[ndx].dwForwardMetric1 = 1255 table->routes[ndx].metric; 1256 /* rest of the metrics are 0.. */ 1257 pIpForwardTable->table[ndx].dwForwardMetric2 = 0; 1258 pIpForwardTable->table[ndx].dwForwardMetric3 = 0; 1259 pIpForwardTable->table[ndx].dwForwardMetric4 = 0; 1260 pIpForwardTable->table[ndx].dwForwardMetric5 = 0; 1261 } 1262 if (bOrder) 1263 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries, 1264 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter); 1265 ret = NO_ERROR; 1266 } 1267 HeapFree(GetProcessHeap(), 0, table); 1268 } 1269 else 1270 ret = ERROR_OUTOFMEMORY; 1271 } 1272 } 1273 TRACE("returning %ld\n", ret); 1274 return ret; 1275 } 1276 1277 1278 static int IpNetTableSorter(const void *a, const void *b) 1279 { 1280 int ret; 1281 1282 if (a && b) 1283 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr; 1284 else 1285 ret = 0; 1286 return ret; 1287 } 1288 1289 1290 /****************************************************************** 1291 * GetIpNetTable (IPHLPAPI.@) 1292 * 1293 * 1294 * PARAMS 1295 * 1296 * pIpNetTable [In/Out] 1297 * pdwSize [In/Out] 1298 * bOrder [In] 1299 * 1300 * RETURNS 1301 * 1302 * DWORD 1303 * 1304 */ 1305 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder) 1306 { 1307 DWORD ret = NO_ERROR; 1308 1309 TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize, 1310 (DWORD)bOrder); 1311 if (!pdwSize) 1312 ret = ERROR_INVALID_PARAMETER; 1313 else { 1314 DWORD numEntries = getNumArpEntries(); 1315 ULONG size = sizeof(MIB_IPNETTABLE); 1316 1317 if (numEntries > 1) 1318 size += (numEntries - 1) * sizeof(MIB_IPNETROW); 1319 if (!pIpNetTable || *pdwSize < size) { 1320 *pdwSize = size; 1321 ret = ERROR_INSUFFICIENT_BUFFER; 1322 } 1323 else { 1324 PMIB_IPNETTABLE table = getArpTable(); 1325 if (table) { 1326 size = sizeof(MIB_IPNETTABLE); 1327 if (table->dwNumEntries > 1) 1328 size += (table->dwNumEntries - 1) * sizeof(MIB_IPNETROW); 1329 if (*pdwSize < size) { 1330 *pdwSize = size; 1331 ret = ERROR_INSUFFICIENT_BUFFER; 1332 } 1333 else { 1334 *pdwSize = size; 1335 memcpy(pIpNetTable, table, size); 1336 if (bOrder) 1337 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries, 1338 sizeof(MIB_IPNETROW), IpNetTableSorter); 1339 ret = NO_ERROR; 1340 } 1341 HeapFree(GetProcessHeap(), 0, table); 1342 } 1343 } 1344 } 1345 TRACE("returning %d\n", ret); 1346 return ret; 1347 } 1348 1349 1350 /****************************************************************** 1351 * GetIpStatistics (IPHLPAPI.@) 1352 * 1353 * 1354 * PARAMS 1355 * 1356 * pStats [In/Out] 1357 * 1358 * RETURNS 1359 * 1360 * DWORD 1361 * 1362 */ 1363 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats) 1364 { 1365 return GetIpStatisticsEx(pStats, PF_INET); 1366 } 1367 1368 /****************************************************************** 1369 * GetIpStatisticsEx (IPHLPAPI.@) 1370 * 1371 * 1372 * PARAMS 1373 * 1374 * pStats [In/Out] 1375 * dwFamily [In] 1376 * 1377 * RETURNS 1378 * 1379 * DWORD 1380 * 1381 */ 1382 DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily) 1383 { 1384 DWORD ret; 1385 1386 TRACE("pStats %p\n", pStats); 1387 ret = getIPStats(pStats, dwFamily); 1388 TRACE("returning %ld\n", ret); 1389 return ret; 1390 } 1391 1392 /****************************************************************** 1393 * GetNetworkParams (IPHLPAPI.@) 1394 * 1395 * 1396 * PARAMS 1397 * 1398 * pFixedInfo [In/Out] 1399 * pOutBufLen [In/Out] 1400 * 1401 * RETURNS 1402 * 1403 * DWORD 1404 * 1405 */ 1406 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) 1407 { 1408 DWORD ret, size, type; 1409 LONG regReturn; 1410 HKEY hKey; 1411 PIPHLP_RES_INFO resInfo; 1412 1413 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen); 1414 if (!pOutBufLen) 1415 return ERROR_INVALID_PARAMETER; 1416 1417 resInfo = getResInfo(); 1418 if (!resInfo) 1419 return ERROR_OUTOFMEMORY; 1420 1421 size = sizeof(FIXED_INFO) + (resInfo->riCount > 1 ? (resInfo->riCount-1) * 1422 sizeof(IP_ADDR_STRING) : 0); 1423 if (!pFixedInfo || *pOutBufLen < size) { 1424 *pOutBufLen = size; 1425 disposeResInfo( resInfo ); 1426 return ERROR_BUFFER_OVERFLOW; 1427 } 1428 1429 memset(pFixedInfo, 0, size); 1430 /* Check for DhcpHostname and DhcpDomain first */ 1431 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 1432 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 1433 0, 1434 KEY_READ, 1435 &hKey); 1436 if (regReturn == ERROR_SUCCESS) { 1437 /* Windows doesn't honor DHCP option 12 even if RFC requires it if it is returned by DHCP server! */ 1438 #if 0 1439 type = REG_SZ; 1440 size = sizeof(pFixedInfo->HostName); 1441 regReturn = RegQueryValueExA(hKey, 1442 "DhcpHostname", 1443 NULL, 1444 &type, 1445 (LPBYTE)pFixedInfo->HostName, 1446 &size); 1447 if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1)) 1448 { 1449 #endif 1450 type = REG_SZ; 1451 size = sizeof(pFixedInfo->HostName); 1452 regReturn = RegQueryValueExA(hKey, 1453 "Hostname", 1454 NULL, 1455 &type, 1456 (LPBYTE)pFixedInfo->HostName, 1457 &size); 1458 #if 0 1459 } 1460 #endif 1461 1462 type = REG_SZ; 1463 size = sizeof(pFixedInfo->DomainName); 1464 regReturn = RegQueryValueExA(hKey, 1465 "DhcpDomain", 1466 NULL, 1467 &type, 1468 (LPBYTE)pFixedInfo->DomainName, 1469 &size); 1470 if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1)) 1471 { 1472 type = REG_SZ; 1473 size = sizeof(pFixedInfo->DomainName); 1474 regReturn = RegQueryValueExA(hKey, 1475 "Domain", 1476 NULL, 1477 &type, 1478 (LPBYTE)pFixedInfo->DomainName, 1479 &size); 1480 } 1481 RegCloseKey(hKey); 1482 } 1483 1484 TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName); 1485 1486 if (resInfo->riCount > 0) 1487 { 1488 CopyMemory(&pFixedInfo->DnsServerList, resInfo->DnsList, sizeof(IP_ADDR_STRING)); 1489 if (resInfo->riCount > 1) 1490 { 1491 IP_ADDR_STRING *pSrc = resInfo->DnsList->Next; 1492 IP_ADDR_STRING *pTarget = (struct _IP_ADDR_STRING*)((char*)pFixedInfo + sizeof(FIXED_INFO)); 1493 1494 pFixedInfo->DnsServerList.Next = pTarget; 1495 1496 do 1497 { 1498 CopyMemory(pTarget, pSrc, sizeof(IP_ADDR_STRING)); 1499 resInfo->riCount--; 1500 if (resInfo->riCount > 1) 1501 { 1502 pTarget->Next = (IP_ADDR_STRING*)((char*)pTarget + sizeof(IP_ADDR_STRING)); 1503 pTarget = pTarget->Next; 1504 pSrc = pSrc->Next; 1505 } 1506 else 1507 { 1508 pTarget->Next = NULL; 1509 break; 1510 } 1511 } 1512 while(TRUE); 1513 } 1514 else 1515 { 1516 pFixedInfo->DnsServerList.Next = NULL; 1517 } 1518 } 1519 1520 pFixedInfo->NodeType = HYBRID_NODETYPE; 1521 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 1522 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey); 1523 if (regReturn != ERROR_SUCCESS) 1524 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 1525 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ, 1526 &hKey); 1527 if (regReturn == ERROR_SUCCESS) 1528 { 1529 DWORD size = sizeof(pFixedInfo->ScopeId); 1530 1531 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (PBYTE)pFixedInfo->ScopeId, &size); 1532 RegCloseKey(hKey); 1533 } 1534 1535 disposeResInfo( resInfo ); 1536 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward 1537 I suppose could also check for a listener on port 53 to set EnableDns */ 1538 ret = NO_ERROR; 1539 TRACE("returning %ld\n", ret); 1540 1541 return ret; 1542 } 1543 1544 1545 /****************************************************************** 1546 * GetNumberOfInterfaces (IPHLPAPI.@) 1547 * 1548 * 1549 * PARAMS 1550 * 1551 * pdwNumIf [In/Out] 1552 * 1553 * RETURNS 1554 * 1555 * DWORD 1556 * 1557 */ 1558 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf) 1559 { 1560 DWORD ret; 1561 1562 TRACE("pdwNumIf %p\n", pdwNumIf); 1563 if (!pdwNumIf) 1564 ret = ERROR_INVALID_PARAMETER; 1565 else { 1566 *pdwNumIf = getNumInterfaces(); 1567 ret = NO_ERROR; 1568 } 1569 TRACE("returning %ld\n", ret); 1570 return ret; 1571 } 1572 1573 1574 /****************************************************************** 1575 * GetOwnerModuleFromTcpEntry (IPHLPAPI.@) 1576 * 1577 * Get data about the module that issued the context bind for a specific IPv4 TCP endpoint in a MIB table row 1578 * 1579 * PARAMS 1580 * pTcpEntry [in] pointer to a MIB_TCPROW_OWNER_MODULE structure 1581 * Class [in] TCPIP_OWNER_MODULE_INFO_CLASS enumeration value 1582 * Buffer [out] pointer a buffer containing a TCPIP_OWNER_MODULE_BASIC_INFO structure with the owner module data. 1583 * pdwSize [in, out] estimated size of the structure returned in Buffer, in bytes 1584 * 1585 * RETURNS 1586 * Success: NO_ERROR 1587 * Failure: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY 1588 * ERROR_NOT_FOUND or ERROR_PARTIAL_COPY 1589 * 1590 * NOTES 1591 * The type of data returned in Buffer is indicated by the value of the Class parameter. 1592 */ 1593 DWORD WINAPI GetOwnerModuleFromTcpEntry( PMIB_TCPROW_OWNER_MODULE pTcpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize) 1594 { 1595 DWORD ret = NO_ERROR; 1596 UNIMPLEMENTED; 1597 return ret; 1598 } 1599 1600 static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, PVOID Data) 1601 { 1602 IP_ADDR_STRING *pNext; 1603 PNAME_SERVER_LIST_CONTEXT Context = (PNAME_SERVER_LIST_CONTEXT)Data; 1604 1605 if (!Context->NumServers) 1606 { 1607 if (Context->uSizeAvailable >= Context->uSizeRequired) 1608 { 1609 WideCharToMultiByte(CP_ACP, 0, Server, -1, Context->pData->DnsServerList.IpAddress.String, 16, NULL, NULL); 1610 Context->pData->DnsServerList.IpAddress.String[15] = '\0'; 1611 Context->pLastAddr = &Context->pData->DnsServerList; 1612 } 1613 } 1614 else 1615 { 1616 Context->uSizeRequired += sizeof(IP_ADDR_STRING); 1617 if (Context->uSizeAvailable >= Context->uSizeRequired) 1618 { 1619 pNext = (IP_ADDR_STRING*)(((char*)Context->pLastAddr) + sizeof(IP_ADDR_STRING)); 1620 WideCharToMultiByte(CP_ACP, 0, Server, -1, pNext->IpAddress.String, 16, NULL, NULL); 1621 pNext->IpAddress.String[15] = '\0'; 1622 Context->pLastAddr->Next = pNext; 1623 Context->pLastAddr = pNext; 1624 pNext->Next = NULL; 1625 } 1626 } 1627 Context->NumServers++; 1628 } 1629 1630 /****************************************************************** 1631 * GetPerAdapterInfo (IPHLPAPI.@) 1632 * 1633 * 1634 * PARAMS 1635 * 1636 * IfIndex [In] 1637 * pPerAdapterInfo [In/Out] 1638 * pOutBufLen [In/Out] 1639 * 1640 * RETURNS 1641 * 1642 * DWORD 1643 * 1644 */ 1645 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen) 1646 { 1647 HKEY hkey; 1648 DWORD dwSize = 0; 1649 const char *ifName; 1650 NAME_SERVER_LIST_CONTEXT Context; 1651 WCHAR keyname[200] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"; 1652 1653 if (!pOutBufLen) 1654 return ERROR_INVALID_PARAMETER; 1655 1656 if (!pPerAdapterInfo || *pOutBufLen < sizeof(IP_PER_ADAPTER_INFO)) 1657 { 1658 *pOutBufLen = sizeof(IP_PER_ADAPTER_INFO); 1659 return ERROR_BUFFER_OVERFLOW; 1660 } 1661 1662 ifName = getInterfaceNameByIndex(IfIndex); 1663 if (!ifName) 1664 return ERROR_INVALID_PARAMETER; 1665 1666 MultiByteToWideChar(CP_ACP, 0, ifName, -1, &keyname[62], sizeof(keyname)/sizeof(WCHAR) - 63); 1667 HeapFree(GetProcessHeap(), 0, (LPVOID)ifName); 1668 1669 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey) != ERROR_SUCCESS) 1670 { 1671 return ERROR_NOT_SUPPORTED; 1672 } 1673 Context.NumServers = 0; 1674 Context.uSizeAvailable = *pOutBufLen; 1675 Context.uSizeRequired = sizeof(IP_PER_ADAPTER_INFO); 1676 Context.pData = pPerAdapterInfo; 1677 1678 if (*pOutBufLen >= sizeof(IP_PER_ADAPTER_INFO)) 1679 ZeroMemory(pPerAdapterInfo, sizeof(IP_PER_ADAPTER_INFO)); 1680 1681 EnumNameServers(hkey, &keyname[62], &Context, CreateNameServerListEnumNamesFunc); 1682 1683 if (Context.uSizeRequired > Context.uSizeAvailable) 1684 { 1685 *pOutBufLen = Context.uSizeRequired; 1686 RegCloseKey(hkey); 1687 return ERROR_BUFFER_OVERFLOW; 1688 } 1689 1690 if(RegQueryValueExW(hkey, L"NameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS) 1691 { 1692 pPerAdapterInfo->AutoconfigActive = FALSE; 1693 } 1694 else 1695 { 1696 pPerAdapterInfo->AutoconfigActive = TRUE; 1697 } 1698 1699 RegCloseKey(hkey); 1700 return NOERROR; 1701 } 1702 1703 1704 /****************************************************************** 1705 * GetRTTAndHopCount (IPHLPAPI.@) 1706 * 1707 * 1708 * PARAMS 1709 * 1710 * DestIpAddress [In] 1711 * HopCount [In/Out] 1712 * MaxHops [In] 1713 * RTT [In/Out] 1714 * 1715 * RETURNS 1716 * 1717 * BOOL 1718 * 1719 */ 1720 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT) 1721 { 1722 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n", 1723 DestIpAddress, HopCount, MaxHops, RTT); 1724 FIXME(":stub\n"); 1725 return (BOOL) 0; 1726 } 1727 1728 1729 /****************************************************************** 1730 * GetTcpStatisticsEx (IPHLPAPI.@) 1731 * 1732 * 1733 * PARAMS 1734 * 1735 * pStats [In/Out] 1736 * dwFamily [In] 1737 * 1738 * RETURNS 1739 * 1740 * DWORD 1741 * 1742 */ 1743 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily) 1744 { 1745 DWORD ret; 1746 1747 TRACE("pStats %p\n", pStats); 1748 ret = getTCPStats(pStats, dwFamily); 1749 TRACE("returning %ld\n", ret); 1750 return ret; 1751 } 1752 1753 /****************************************************************** 1754 * GetTcpStatistics (IPHLPAPI.@) 1755 * 1756 * 1757 * PARAMS 1758 * 1759 * pStats [In/Out] 1760 * 1761 * RETURNS 1762 * 1763 * DWORD 1764 * 1765 */ 1766 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats) 1767 { 1768 return GetTcpStatisticsEx(pStats, PF_INET); 1769 } 1770 1771 1772 static int TcpTableSorter(const void *a, const void *b) 1773 { 1774 int ret; 1775 1776 if (a && b) { 1777 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b; 1778 1779 ret = rowA->dwLocalAddr - rowB->dwLocalAddr; 1780 if (ret == 0) { 1781 ret = rowA->dwLocalPort - rowB->dwLocalPort; 1782 if (ret == 0) { 1783 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr; 1784 if (ret == 0) 1785 ret = rowA->dwRemotePort - rowB->dwRemotePort; 1786 } 1787 } 1788 } 1789 else 1790 ret = 0; 1791 return ret; 1792 } 1793 1794 1795 /****************************************************************** 1796 * GetTcpTable (IPHLPAPI.@) 1797 * 1798 * Get the table of active TCP connections. 1799 * 1800 * PARAMS 1801 * pTcpTable [Out] buffer for TCP connections table 1802 * pdwSize [In/Out] length of output buffer 1803 * bOrder [In] whether to order the table 1804 * 1805 * RETURNS 1806 * Success: NO_ERROR 1807 * Failure: error code from winerror.h 1808 * 1809 * NOTES 1810 * If pdwSize is less than required, the function will return 1811 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to 1812 * the required byte size. 1813 * If bOrder is true, the returned table will be sorted, first by 1814 * local address and port number, then by remote address and port 1815 * number. 1816 */ 1817 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder) 1818 { 1819 DWORD ret = ERROR_NO_DATA; 1820 1821 TRACE("pTcpTable %p, pdwSize %p, bOrder %d\n", pTcpTable, pdwSize, 1822 (DWORD)bOrder); 1823 if (!pdwSize) 1824 ret = ERROR_INVALID_PARAMETER; 1825 else { 1826 DWORD numEntries = getNumTcpEntries(); 1827 DWORD size = sizeof(MIB_TCPTABLE); 1828 1829 if (numEntries > 1) 1830 size += (numEntries - 1) * sizeof(MIB_TCPROW); 1831 if (!pTcpTable || *pdwSize < size) { 1832 *pdwSize = size; 1833 ret = ERROR_INSUFFICIENT_BUFFER; 1834 } 1835 else { 1836 PMIB_TCPTABLE pOurTcpTable = getTcpTable(); 1837 if (pOurTcpTable) 1838 { 1839 size = sizeof(MIB_TCPTABLE); 1840 if (pOurTcpTable->dwNumEntries > 1) 1841 size += (pOurTcpTable->dwNumEntries - 1) * sizeof(MIB_TCPROW); 1842 1843 if (*pdwSize < size) 1844 { 1845 *pdwSize = size; 1846 1847 ret = ERROR_INSUFFICIENT_BUFFER; 1848 } 1849 else 1850 { 1851 memcpy(pTcpTable, pOurTcpTable, size); 1852 1853 if (bOrder) 1854 qsort(pTcpTable->table, pTcpTable->dwNumEntries, 1855 sizeof(MIB_TCPROW), TcpTableSorter); 1856 1857 ret = NO_ERROR; 1858 } 1859 1860 free(pOurTcpTable); 1861 } 1862 } 1863 } 1864 TRACE("returning %d\n", ret); 1865 return ret; 1866 } 1867 1868 1869 /****************************************************************** 1870 * GetUdpStatisticsEx (IPHLPAPI.@) 1871 * 1872 * 1873 * PARAMS 1874 * 1875 * pStats [In/Out] 1876 * dwFamily [In] 1877 * 1878 * RETURNS 1879 * 1880 * DWORD 1881 * 1882 */ 1883 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily) 1884 { 1885 DWORD ret; 1886 1887 TRACE("pStats %p\n", pStats); 1888 ret = getUDPStats(pStats, dwFamily); 1889 TRACE("returning %ld\n", ret); 1890 return ret; 1891 } 1892 1893 /****************************************************************** 1894 * GetUdpStatistics (IPHLPAPI.@) 1895 * 1896 * 1897 * PARAMS 1898 * 1899 * pStats [In/Out] 1900 * 1901 * RETURNS 1902 * 1903 * DWORD 1904 * 1905 */ 1906 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats) 1907 { 1908 return GetUdpStatisticsEx(pStats, PF_INET); 1909 } 1910 1911 1912 static int UdpTableSorter(const void *a, const void *b) 1913 { 1914 int ret; 1915 1916 if (a && b) { 1917 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b; 1918 1919 ret = rowA->dwLocalAddr - rowB->dwLocalAddr; 1920 if (ret == 0) 1921 ret = rowA->dwLocalPort - rowB->dwLocalPort; 1922 } 1923 else 1924 ret = 0; 1925 return ret; 1926 } 1927 1928 1929 /****************************************************************** 1930 * GetUdpTable (IPHLPAPI.@) 1931 * 1932 * 1933 * PARAMS 1934 * 1935 * pUdpTable [In/Out] 1936 * pdwSize [In/Out] 1937 * bOrder [In] 1938 * 1939 * RETURNS 1940 * 1941 * DWORD 1942 * 1943 */ 1944 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder) 1945 { 1946 DWORD ret; 1947 1948 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize, 1949 (DWORD)bOrder); 1950 if (!pdwSize) 1951 ret = ERROR_INVALID_PARAMETER; 1952 else { 1953 DWORD numEntries = getNumUdpEntries(); 1954 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW); 1955 1956 if (!pUdpTable || *pdwSize < size) { 1957 *pdwSize = size; 1958 ret = ERROR_INSUFFICIENT_BUFFER; 1959 } 1960 else { 1961 PMIB_UDPTABLE table = getUdpTable(); 1962 1963 if (table) { 1964 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) * 1965 sizeof(MIB_UDPROW); 1966 if (*pdwSize < size) { 1967 *pdwSize = size; 1968 ret = ERROR_INSUFFICIENT_BUFFER; 1969 } 1970 else { 1971 memcpy(pUdpTable, table, size); 1972 if (bOrder) 1973 qsort(pUdpTable->table, pUdpTable->dwNumEntries, 1974 sizeof(MIB_UDPROW), UdpTableSorter); 1975 ret = NO_ERROR; 1976 } 1977 free(table); 1978 } 1979 else 1980 ret = ERROR_OUTOFMEMORY; 1981 } 1982 } 1983 TRACE("returning %ld\n", ret); 1984 return ret; 1985 } 1986 1987 1988 /****************************************************************** 1989 * GetUniDirectionalAdapterInfo (IPHLPAPI.@) 1990 * 1991 * This is a Win98-only function to get information on "unidirectional" 1992 * adapters. Since this is pretty nonsensical in other contexts, it 1993 * never returns anything. 1994 * 1995 * PARAMS 1996 * pIPIfInfo [Out] buffer for adapter infos 1997 * dwOutBufLen [Out] length of the output buffer 1998 * 1999 * RETURNS 2000 * Success: NO_ERROR 2001 * Failure: error code from winerror.h 2002 * 2003 * FIXME 2004 * Stub, returns ERROR_NOT_SUPPORTED. 2005 */ 2006 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen) 2007 { 2008 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen); 2009 /* a unidirectional adapter?? not bloody likely! */ 2010 return ERROR_NOT_SUPPORTED; 2011 } 2012 2013 2014 /****************************************************************** 2015 * IpReleaseAddress (IPHLPAPI.@) 2016 * 2017 * Release an IP obtained through DHCP, 2018 * 2019 * PARAMS 2020 * AdapterInfo [In] adapter to release IP address 2021 * 2022 * RETURNS 2023 * Success: NO_ERROR 2024 * Failure: error code from winerror.h 2025 * 2026 */ 2027 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) 2028 { 2029 DWORD Status, Version = 0; 2030 2031 if (!AdapterInfo) 2032 return ERROR_INVALID_PARAMETER; 2033 2034 /* Maybe we should do this in DllMain */ 2035 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS) 2036 return ERROR_PROC_NOT_FOUND; 2037 2038 if (DhcpReleaseIpAddressLease(AdapterInfo->Index)) 2039 Status = ERROR_SUCCESS; 2040 else 2041 Status = ERROR_PROC_NOT_FOUND; 2042 2043 DhcpCApiCleanup(); 2044 2045 return Status; 2046 } 2047 2048 2049 /****************************************************************** 2050 * IpRenewAddress (IPHLPAPI.@) 2051 * 2052 * Renew an IP obtained through DHCP. 2053 * 2054 * PARAMS 2055 * AdapterInfo [In] adapter to renew IP address 2056 * 2057 * RETURNS 2058 * Success: NO_ERROR 2059 * Failure: error code from winerror.h 2060 */ 2061 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) 2062 { 2063 DWORD Status, Version = 0; 2064 2065 if (!AdapterInfo) 2066 return ERROR_INVALID_PARAMETER; 2067 2068 /* Maybe we should do this in DllMain */ 2069 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS) 2070 return ERROR_PROC_NOT_FOUND; 2071 2072 if (DhcpRenewIpAddressLease(AdapterInfo->Index)) 2073 Status = ERROR_SUCCESS; 2074 else 2075 Status = ERROR_PROC_NOT_FOUND; 2076 2077 DhcpCApiCleanup(); 2078 2079 return Status; 2080 } 2081 2082 2083 /****************************************************************** 2084 * NotifyAddrChange (IPHLPAPI.@) 2085 * 2086 * Notify caller whenever the ip-interface map is changed. 2087 * 2088 * PARAMS 2089 * Handle [Out] handle usable in asynchronous notification 2090 * overlapped [In] overlapped structure that notifies the caller 2091 * 2092 * RETURNS 2093 * Success: NO_ERROR 2094 * Failure: error code from winerror.h 2095 * 2096 * FIXME 2097 * Stub, returns ERROR_NOT_SUPPORTED. 2098 */ 2099 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped) 2100 { 2101 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped); 2102 if (Handle) *Handle = INVALID_HANDLE_VALUE; 2103 if (overlapped) ((IO_STATUS_BLOCK *) overlapped)->Status = STATUS_PENDING; 2104 return ERROR_IO_PENDING; 2105 } 2106 2107 2108 /****************************************************************** 2109 * NotifyRouteChange (IPHLPAPI.@) 2110 * 2111 * Notify caller whenever the ip routing table is changed. 2112 * 2113 * PARAMS 2114 * Handle [Out] handle usable in asynchronous notification 2115 * overlapped [In] overlapped structure that notifies the caller 2116 * 2117 * RETURNS 2118 * Success: NO_ERROR 2119 * Failure: error code from winerror.h 2120 * 2121 * FIXME 2122 * Stub, returns ERROR_NOT_SUPPORTED. 2123 */ 2124 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped) 2125 { 2126 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped); 2127 return ERROR_NOT_SUPPORTED; 2128 } 2129 2130 /****************************************************************** 2131 * SendARP (IPHLPAPI.@) 2132 * 2133 * Send an ARP request. 2134 * 2135 * PARAMS 2136 * DestIP [In] attempt to obtain this IP 2137 * SrcIP [In] optional sender IP address 2138 * pMacAddr [Out] buffer for the mac address 2139 * PhyAddrLen [In/Out] length of the output buffer 2140 * 2141 * RETURNS 2142 * Success: NO_ERROR 2143 * Failure: error code from winerror.h 2144 */ 2145 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen) 2146 { 2147 IPAddr IPs[2]; 2148 ULONG Size; 2149 2150 if (IsBadWritePtr(pMacAddr, sizeof(ULONG)) || IsBadWritePtr(PhyAddrLen, sizeof(ULONG))) 2151 return ERROR_INVALID_PARAMETER; 2152 2153 IPs[0] = DestIP; 2154 IPs[1] = SrcIP; 2155 Size = sizeof(IPs); 2156 return TCPSendIoctl(INVALID_HANDLE_VALUE, IOCTL_QUERY_IP_HW_ADDRESS, IPs, &Size, pMacAddr, PhyAddrLen); 2157 } 2158 2159 2160 /****************************************************************** 2161 * SetIfEntry (IPHLPAPI.@) 2162 * 2163 * Set the administrative status of an interface. 2164 * 2165 * PARAMS 2166 * pIfRow [In] dwAdminStatus member specifies the new status. 2167 * 2168 * RETURNS 2169 * Success: NO_ERROR 2170 * Failure: error code from winerror.h 2171 * 2172 * FIXME 2173 * Stub, returns ERROR_NOT_SUPPORTED. 2174 */ 2175 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow) 2176 { 2177 FIXME("(pIfRow %p): stub\n", pIfRow); 2178 /* this is supposed to set an interface administratively up or down. 2179 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and 2180 this sort of down is indistinguishable from other sorts of down (e.g. no 2181 link). */ 2182 return ERROR_NOT_SUPPORTED; 2183 } 2184 2185 2186 /****************************************************************** 2187 * SetIpForwardEntry (IPHLPAPI.@) 2188 * 2189 * Modify an existing route. 2190 * 2191 * PARAMS 2192 * pRoute [In] route with the new information 2193 * 2194 * RETURNS 2195 * Success: NO_ERROR 2196 * Failure: error code from winerror.h 2197 * 2198 */ 2199 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute) 2200 { 2201 return setIpForwardEntry( pRoute ); 2202 } 2203 2204 2205 /****************************************************************** 2206 * SetIpNetEntry (IPHLPAPI.@) 2207 * 2208 * Modify an existing ARP entry. 2209 * 2210 * PARAMS 2211 * pArpEntry [In] ARP entry with the new information 2212 * 2213 * RETURNS 2214 * Success: NO_ERROR 2215 * Failure: error code from winerror.h 2216 */ 2217 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry) 2218 { 2219 HANDLE tcpFile; 2220 NTSTATUS status; 2221 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req = 2222 TCP_REQUEST_SET_INFORMATION_INIT; 2223 TDIEntityID id; 2224 DWORD returnSize; 2225 PMIB_IPNETROW arpBuff; 2226 2227 if (!pArpEntry) 2228 return ERROR_INVALID_PARAMETER; 2229 2230 if (!NT_SUCCESS(openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ))) 2231 return ERROR_NOT_SUPPORTED; 2232 2233 if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id ))) 2234 { 2235 closeTcpFile(tcpFile); 2236 return ERROR_INVALID_PARAMETER; 2237 } 2238 2239 req.Req.ID.toi_class = INFO_CLASS_PROTOCOL; 2240 req.Req.ID.toi_type = INFO_TYPE_PROVIDER; 2241 req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID; 2242 req.Req.ID.toi_entity.tei_instance = id.tei_instance; 2243 req.Req.ID.toi_entity.tei_entity = AT_ENTITY; 2244 req.Req.BufferSize = sizeof(MIB_IPNETROW); 2245 arpBuff = (PMIB_IPNETROW)&req.Req.Buffer[0]; 2246 2247 RtlCopyMemory(arpBuff, pArpEntry, sizeof(MIB_IPNETROW)); 2248 2249 status = DeviceIoControl( tcpFile, 2250 IOCTL_TCP_SET_INFORMATION_EX, 2251 &req, 2252 sizeof(req), 2253 NULL, 2254 0, 2255 &returnSize, 2256 NULL ); 2257 2258 closeTcpFile(tcpFile); 2259 2260 if (status) 2261 return NO_ERROR; 2262 else 2263 return ERROR_INVALID_PARAMETER; 2264 } 2265 2266 2267 /****************************************************************** 2268 * SetIpStatistics (IPHLPAPI.@) 2269 * 2270 * Toggle IP forwarding and det the default TTL value. 2271 * 2272 * PARAMS 2273 * pIpStats [In] IP statistics with the new information 2274 * 2275 * RETURNS 2276 * Success: NO_ERROR 2277 * Failure: error code from winerror.h 2278 * 2279 * FIXME 2280 * Stub, returns NO_ERROR. 2281 */ 2282 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats) 2283 { 2284 FIXME("(pIpStats %p): stub\n", pIpStats); 2285 return 0; 2286 } 2287 2288 2289 /****************************************************************** 2290 * SetIpTTL (IPHLPAPI.@) 2291 * 2292 * Set the default TTL value. 2293 * 2294 * PARAMS 2295 * nTTL [In] new TTL value 2296 * 2297 * RETURNS 2298 * Success: NO_ERROR 2299 * Failure: error code from winerror.h 2300 * 2301 * FIXME 2302 * Stub, returns NO_ERROR. 2303 */ 2304 DWORD WINAPI SetIpTTL(UINT nTTL) 2305 { 2306 FIXME("(nTTL %d): stub\n", nTTL); 2307 return 0; 2308 } 2309 2310 2311 /****************************************************************** 2312 * SetTcpEntry (IPHLPAPI.@) 2313 * 2314 * Set the state of a TCP connection. 2315 * 2316 * PARAMS 2317 * pTcpRow [In] specifies connection with new state 2318 * 2319 * RETURNS 2320 * Success: NO_ERROR 2321 * Failure: error code from winerror.h 2322 * 2323 * FIXME 2324 * Stub, returns NO_ERROR. 2325 */ 2326 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow) 2327 { 2328 FIXME("(pTcpRow %p): stub\n", pTcpRow); 2329 return 0; 2330 } 2331 2332 2333 /****************************************************************** 2334 * UnenableRouter (IPHLPAPI.@) 2335 * 2336 * Decrement the IP-forwarding reference count. Turn off IP-forwarding 2337 * if it reaches zero. 2338 * 2339 * PARAMS 2340 * pOverlapped [In/Out] should be the same as in EnableRouter() 2341 * lpdwEnableCount [Out] optional, receives reference count 2342 * 2343 * RETURNS 2344 * Success: NO_ERROR 2345 * Failure: error code from winerror.h 2346 * 2347 * FIXME 2348 * Stub, returns ERROR_NOT_SUPPORTED. 2349 */ 2350 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount) 2351 { 2352 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped, 2353 lpdwEnableCount); 2354 return ERROR_NOT_SUPPORTED; 2355 } 2356 2357 /* 2358 * @unimplemented 2359 */ 2360 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size) 2361 { 2362 FIXME(":stub\n"); 2363 return 0L; 2364 } 2365 2366 2367 /* 2368 * @unimplemented 2369 */ 2370 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID) 2371 { 2372 FIXME(":stub\n"); 2373 return 0L; 2374 } 2375 2376 /* 2377 * @implemented 2378 */ 2379 #ifdef GetAdaptersAddressesV1 2380 DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen) 2381 { 2382 InterfaceIndexTable *indexTable; 2383 IFInfo ifInfo; 2384 int i; 2385 ULONG ret, requiredSize = 0; 2386 PIP_ADAPTER_ADDRESSES currentAddress; 2387 PUCHAR currentLocation; 2388 HANDLE tcpFile; 2389 2390 if (!pOutBufLen) return ERROR_INVALID_PARAMETER; 2391 if (Reserved) return ERROR_INVALID_PARAMETER; 2392 2393 indexTable = getInterfaceIndexTable(); 2394 if (!indexTable) 2395 return ERROR_NOT_ENOUGH_MEMORY; 2396 2397 ret = openTcpFile(&tcpFile, FILE_READ_DATA); 2398 if (!NT_SUCCESS(ret)) 2399 return ERROR_NO_DATA; 2400 2401 for (i = indexTable->numIndexes; i >= 0; i--) 2402 { 2403 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, 2404 NULL, 2405 indexTable->indexes[i], 2406 &ifInfo))) 2407 { 2408 /* The whole struct */ 2409 requiredSize += sizeof(IP_ADAPTER_ADDRESSES); 2410 2411 /* Friendly name */ 2412 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) 2413 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1; //FIXME 2414 2415 /* Adapter name */ 2416 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1; 2417 2418 /* Unicast address */ 2419 if (!(Flags & GAA_FLAG_SKIP_UNICAST)) 2420 requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS); 2421 2422 /* FIXME: Implement multicast, anycast, and dns server stuff */ 2423 2424 /* FIXME: Implement dns suffix and description */ 2425 requiredSize += 2 * sizeof(WCHAR); 2426 2427 /* We're only going to implement what's required for XP SP0 */ 2428 } 2429 } 2430 TRACE("size: %d, requiredSize: %d\n", *pOutBufLen, requiredSize); 2431 if (!pAdapterAddresses || *pOutBufLen < requiredSize) 2432 { 2433 *pOutBufLen = requiredSize; 2434 closeTcpFile(tcpFile); 2435 free(indexTable); 2436 return ERROR_BUFFER_OVERFLOW; 2437 } 2438 2439 RtlZeroMemory(pAdapterAddresses, requiredSize); 2440 2441 /* Let's set up the pointers */ 2442 currentAddress = pAdapterAddresses; 2443 for (i = indexTable->numIndexes; i >= 0; i--) 2444 { 2445 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, 2446 NULL, 2447 indexTable->indexes[i], 2448 &ifInfo))) 2449 { 2450 currentLocation = (PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES); 2451 2452 /* FIXME: Friendly name */ 2453 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) 2454 { 2455 currentAddress->FriendlyName = (PVOID)currentLocation; 2456 currentLocation += sizeof(WCHAR); 2457 } 2458 2459 /* Adapter name */ 2460 currentAddress->AdapterName = (PVOID)currentLocation; 2461 currentLocation += strlen((char *)ifInfo.if_info.ent.if_descr) + 1; 2462 2463 /* Unicast address */ 2464 if (!(Flags & GAA_FLAG_SKIP_UNICAST)) 2465 { 2466 currentAddress->FirstUnicastAddress = (PVOID)currentLocation; 2467 currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS); 2468 currentAddress->FirstUnicastAddress->Address.lpSockaddr = (PVOID)currentLocation; 2469 currentLocation += sizeof(struct sockaddr); 2470 } 2471 2472 /* FIXME: Implement multicast, anycast, and dns server stuff */ 2473 2474 /* FIXME: Implement dns suffix and description */ 2475 currentAddress->DnsSuffix = (PVOID)currentLocation; 2476 currentLocation += sizeof(WCHAR); 2477 2478 currentAddress->Description = (PVOID)currentLocation; 2479 currentLocation += sizeof(WCHAR); 2480 2481 currentAddress->Next = (PVOID)currentLocation; 2482 /* Terminate the last address correctly */ 2483 if(i==0) 2484 currentAddress->Next = NULL; 2485 2486 /* We're only going to implement what's required for XP SP0 */ 2487 2488 currentAddress = currentAddress->Next; 2489 } 2490 } 2491 2492 /* Now again, for real this time */ 2493 2494 currentAddress = pAdapterAddresses; 2495 for (i = indexTable->numIndexes; i >= 0; i--) 2496 { 2497 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile, 2498 NULL, 2499 indexTable->indexes[i], 2500 &ifInfo))) 2501 { 2502 /* Make sure we're not looping more than we hoped for */ 2503 ASSERT(currentAddress); 2504 2505 /* Alignment information */ 2506 currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES); 2507 currentAddress->IfIndex = indexTable->indexes[i]; 2508 2509 /* Adapter name */ 2510 strcpy(currentAddress->AdapterName, (char *)ifInfo.if_info.ent.if_descr); 2511 2512 if (!(Flags & GAA_FLAG_SKIP_UNICAST)) 2513 { 2514 currentAddress->FirstUnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS); 2515 currentAddress->FirstUnicastAddress->Flags = 0; //FIXME 2516 currentAddress->FirstUnicastAddress->Next = NULL; //FIXME: Support more than one address per adapter 2517 currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family = AF_INET; 2518 memcpy(currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data, 2519 &ifInfo.ip_addr.iae_addr, 2520 sizeof(ifInfo.ip_addr.iae_addr)); 2521 currentAddress->FirstUnicastAddress->Address.iSockaddrLength = sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT); 2522 currentAddress->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther; //FIXME 2523 currentAddress->FirstUnicastAddress->SuffixOrigin = IpPrefixOriginOther; //FIXME 2524 currentAddress->FirstUnicastAddress->DadState = IpDadStatePreferred; //FIXME 2525 currentAddress->FirstUnicastAddress->ValidLifetime = 0xFFFFFFFF; //FIXME 2526 currentAddress->FirstUnicastAddress->PreferredLifetime = 0xFFFFFFFF; //FIXME 2527 currentAddress->FirstUnicastAddress->LeaseLifetime = 0xFFFFFFFF; //FIXME 2528 } 2529 2530 /* FIXME: Implement multicast, anycast, and dns server stuff */ 2531 currentAddress->FirstAnycastAddress = NULL; 2532 currentAddress->FirstMulticastAddress = NULL; 2533 currentAddress->FirstDnsServerAddress = NULL; 2534 2535 /* FIXME: Implement dns suffix, description, and friendly name */ 2536 currentAddress->DnsSuffix[0] = UNICODE_NULL; 2537 currentAddress->Description[0] = UNICODE_NULL; 2538 currentAddress->FriendlyName[0] = UNICODE_NULL; 2539 2540 /* Physical Address */ 2541 memcpy(currentAddress->PhysicalAddress, ifInfo.if_info.ent.if_physaddr, ifInfo.if_info.ent.if_physaddrlen); 2542 currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen; 2543 2544 /* Flags */ 2545 currentAddress->Flags = 0; //FIXME 2546 2547 /* MTU */ 2548 currentAddress->Mtu = ifInfo.if_info.ent.if_mtu; 2549 2550 /* Interface type */ 2551 currentAddress->IfType = ifInfo.if_info.ent.if_type; 2552 2553 /* Operational status */ 2554 if(ifInfo.if_info.ent.if_operstatus >= IF_OPER_STATUS_CONNECTING) 2555 currentAddress->OperStatus = IfOperStatusUp; 2556 else 2557 currentAddress->OperStatus = IfOperStatusDown; 2558 2559 /* We're only going to implement what's required for XP SP0 */ 2560 2561 /* Move to the next address */ 2562 currentAddress = currentAddress->Next; 2563 } 2564 } 2565 2566 closeTcpFile(tcpFile); 2567 free(indexTable); 2568 2569 return NO_ERROR; 2570 } 2571 #endif 2572 2573 /* 2574 * @unimplemented 2575 */ 2576 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped) 2577 { 2578 FIXME(":stub\n"); 2579 return 0L; 2580 } 2581 2582 /* 2583 * @unimplemented 2584 */ 2585 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex) 2586 { 2587 FIXME(":stub\n"); 2588 return 0L; 2589 } 2590 2591 /* 2592 * @unimplemented 2593 */ 2594 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags) 2595 { 2596 FIXME(":stub\n"); 2597 return 0L; 2598 } 2599 2600 /* 2601 * @unimplemented 2602 */ 2603 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily) 2604 { 2605 FIXME(":stub\n"); 2606 2607 if (!pStats) 2608 return ERROR_INVALID_PARAMETER; 2609 2610 if (dwFamily != AF_INET && dwFamily != AF_INET6) 2611 return ERROR_INVALID_PARAMETER; 2612 2613 return 0L; 2614 } 2615 2616 DWORD WINAPI 2617 SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute) 2618 { 2619 FIXME("SetIpForwardEntryToStack() stub\n"); 2620 return 0L; 2621 } 2622 2623 DWORD GetInterfaceNameInternal(_In_ const GUID * pInterfaceGUID, 2624 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName, 2625 _Inout_ PULONG pOutBufLen) 2626 { 2627 UNICODE_STRING GuidString; 2628 DWORD result, type; 2629 WCHAR szKeyName[2*MAX_PATH]; 2630 HRESULT hr; 2631 HKEY hKey; 2632 2633 if (pInterfaceGUID == NULL || pOutBufLen == NULL) 2634 return ERROR_INVALID_PARAMETER; 2635 2636 result = RtlStringFromGUID(pInterfaceGUID, &GuidString); 2637 2638 if (!NT_SUCCESS(result)) 2639 { 2640 // failed to convert guid to string 2641 return RtlNtStatusToDosError(result); 2642 } 2643 2644 hr = StringCbPrintfW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", GuidString.Buffer); 2645 RtlFreeUnicodeString(&GuidString); 2646 2647 if (FAILED(hr)) 2648 { 2649 // key name is too long 2650 return ERROR_BUFFER_OVERFLOW; 2651 } 2652 2653 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKey); 2654 2655 if (result != ERROR_SUCCESS) 2656 { 2657 // failed to find adapter entry 2658 return ERROR_NOT_FOUND; 2659 } 2660 2661 result = RegQueryValueExW(hKey, L"Name", NULL, &type, (PVOID)pInterfaceName, pOutBufLen); 2662 2663 RegCloseKey(hKey); 2664 2665 if (result == ERROR_MORE_DATA) 2666 { 2667 *pOutBufLen = MAX_INTERFACE_NAME_LEN * 2; 2668 return ERROR_INSUFFICIENT_BUFFER; 2669 } 2670 2671 if (result != ERROR_SUCCESS || type != REG_SZ) 2672 { 2673 // failed to read adapter name 2674 return ERROR_NO_DATA; 2675 } 2676 return ERROR_SUCCESS; 2677 } 2678 2679 /* 2680 * @implemented 2681 */ 2682 DWORD WINAPI 2683 NhGetInterfaceNameFromDeviceGuid(_In_ const GUID * pInterfaceGUID, 2684 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName, 2685 _Inout_ PULONG pOutBufLen, 2686 DWORD dwUnknown4, 2687 DWORD dwUnknown5) 2688 { 2689 SetLastError(ERROR_SUCCESS); 2690 2691 if (pInterfaceName == NULL) 2692 return ERROR_INVALID_PARAMETER; 2693 2694 return GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen); 2695 } 2696 2697 /* 2698 * @implemented 2699 */ 2700 DWORD WINAPI 2701 NhGetInterfaceNameFromGuid(_In_ const GUID * pInterfaceGUID, 2702 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName, 2703 _Inout_ PULONG pOutBufLen, 2704 DWORD dwUnknown4, 2705 DWORD dwUnknown5) 2706 { 2707 DWORD result; 2708 2709 result = GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen); 2710 2711 if (result == ERROR_NOT_FOUND) 2712 SetLastError(ERROR_PATH_NOT_FOUND); 2713 2714 return result; 2715 } 2716