1 /* Copyright (C) 2003 Art Yerkes 2 * A reimplementation of ifenum.c by Juan Lang 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * Implementation notes 19 * - Our bretheren use IOCTL_TCP_QUERY_INFORMATION_EX to get information 20 * from tcpip.sys and IOCTL_TCP_SET_INFORMATION_EX to set info (such as 21 * the route table). These ioctls mirror WsControl exactly in usage. 22 * - This iphlpapi does not rely on any reactos-only features. 23 * - This implementation is meant to be largely correct. I am not, however, 24 * paying any attention to performance. It can be done faster, and 25 * someone should definately optimize this code when speed is more of a 26 * priority than it is now. 27 * 28 * Edited implementation notes from the original -- Basically edited to add 29 * information and prune things which are not accurate about this file. 30 * Interface index fun: 31 * - Windows may rely on an index being cleared in the topmost 8 bits in some 32 * APIs; see GetFriendlyIfIndex and the mention of "backward compatible" 33 * indexes. It isn't clear which APIs might fail with non-backward-compatible 34 * indexes, but I'll keep them bits clear just in case. 35 * FIXME: 36 * - We don't support IPv6 addresses here yet -- I moved the upper edge 37 * functions into iphlpv6.c (arty) 38 */ 39 #include "iphlpapi_private.h" 40 41 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); 42 43 /* Functions */ 44 45 /* I'm a bit skittish about maintaining this info in memory, as I'd rather 46 * not add any mutex or critical section blockers to these functions. I've 47 * encountered far too many windows functions that contribute to deadlock 48 * by not announcing themselves. */ 49 void interfaceMapInit(void) 50 { 51 /* For now, nothing */ 52 } 53 54 void interfaceMapFree(void) 55 { 56 /* Ditto. */ 57 } 58 59 NTSTATUS tdiGetMibForIfEntity 60 ( HANDLE tcpFile, TDIEntityID *ent, IFEntrySafelySized *entry ) { 61 TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT; 62 NTSTATUS status = STATUS_SUCCESS; 63 DWORD returnSize; 64 65 WARN("TdiGetMibForIfEntity(tcpFile %p,entityId %p)\n", 66 tcpFile, ent->tei_instance); 67 68 req.ID.toi_class = INFO_CLASS_PROTOCOL; 69 req.ID.toi_type = INFO_TYPE_PROVIDER; 70 req.ID.toi_id = IF_MIB_STATS_ID; 71 req.ID.toi_entity = *ent; 72 73 status = DeviceIoControl( tcpFile, 74 IOCTL_TCP_QUERY_INFORMATION_EX, 75 &req, 76 sizeof(req), 77 entry, 78 sizeof(*entry), 79 &returnSize, 80 NULL ); 81 82 if(!status) 83 { 84 WARN("IOCTL Failed\n"); 85 return STATUS_UNSUCCESSFUL; 86 } 87 88 TRACE("TdiGetMibForIfEntity() => {\n" 89 " if_index ....................... %x\n" 90 " if_type ........................ %x\n" 91 " if_mtu ......................... %d\n" 92 " if_speed ....................... %x\n" 93 " if_physaddrlen ................. %d\n", 94 entry->ent.if_index, 95 entry->ent.if_type, 96 entry->ent.if_mtu, 97 entry->ent.if_speed, 98 entry->ent.if_physaddrlen); 99 TRACE(" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n" 100 " if_descr ....................... %s\n", 101 entry->ent.if_physaddr[0] & 0xff, 102 entry->ent.if_physaddr[1] & 0xff, 103 entry->ent.if_physaddr[2] & 0xff, 104 entry->ent.if_physaddr[3] & 0xff, 105 entry->ent.if_physaddr[4] & 0xff, 106 entry->ent.if_physaddr[5] & 0xff, 107 entry->ent.if_descr); 108 TRACE("} status %08x\n",status); 109 110 return STATUS_SUCCESS; 111 } 112 113 BOOL isInterface( TDIEntityID *if_maybe ) { 114 return 115 if_maybe->tei_entity == IF_ENTITY; 116 } 117 118 BOOL isLoopback( HANDLE tcpFile, TDIEntityID *loop_maybe ) { 119 IFEntrySafelySized entryInfo; 120 NTSTATUS status; 121 122 status = tdiGetMibForIfEntity( tcpFile, 123 loop_maybe, 124 &entryInfo ); 125 126 return NT_SUCCESS(status) && 127 (entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK); 128 } 129 130 BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) { 131 TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT; 132 NTSTATUS status = STATUS_SUCCESS; 133 DWORD returnSize, type; 134 135 req.ID.toi_class = INFO_CLASS_GENERIC; 136 req.ID.toi_type = INFO_TYPE_PROVIDER; 137 req.ID.toi_id = ENTITY_TYPE_ID; 138 req.ID.toi_entity.tei_entity = AT_ENTITY; 139 req.ID.toi_entity.tei_instance = arp_maybe->tei_instance; 140 141 status = DeviceIoControl( tcpFile, 142 IOCTL_TCP_QUERY_INFORMATION_EX, 143 &req, 144 sizeof(req), 145 &type, 146 sizeof(type), 147 &returnSize, 148 NULL ); 149 if( !NT_SUCCESS(status) ) return FALSE; 150 151 return (type & AT_ARP); 152 } 153 154 static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile, 155 IFInfo **infoSet, 156 PDWORD numInterfaces ) { 157 DWORD numEntities; 158 TDIEntityID *entIDSet = NULL; 159 NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entIDSet, &numEntities ); 160 IFInfo *infoSetInt = 0; 161 int curInterf = 0, i; 162 163 if (!NT_SUCCESS(status)) { 164 ERR("getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status); 165 return status; 166 } 167 168 infoSetInt = HeapAlloc( GetProcessHeap(), 0, 169 sizeof(IFInfo) * numEntities ); 170 171 if( infoSetInt ) { 172 for( i = 0; i < numEntities; i++ ) { 173 if( isInterface( &entIDSet[i] ) ) { 174 infoSetInt[curInterf].entity_id = entIDSet[i]; 175 status = tdiGetMibForIfEntity 176 ( tcpFile, 177 &entIDSet[i], 178 &infoSetInt[curInterf].if_info ); 179 TRACE("tdiGetMibForIfEntity: %08x\n", status); 180 if( NT_SUCCESS(status) ) { 181 DWORD numAddrs; 182 IPAddrEntry *addrs; 183 TDIEntityID ip_ent; 184 int j; 185 186 status = getNthIpEntity( tcpFile, curInterf, &ip_ent ); 187 if( NT_SUCCESS(status) ) 188 status = tdiGetIpAddrsForIpEntity 189 ( tcpFile, &ip_ent, &addrs, &numAddrs ); 190 for( j = 0; NT_SUCCESS(status) && j < numAddrs; j++ ) { 191 TRACE("ADDR %d: index %d (target %d)\n", j, addrs[j].iae_index, infoSetInt[curInterf].if_info.ent.if_index); 192 if( addrs[j].iae_index == 193 infoSetInt[curInterf].if_info.ent.if_index ) { 194 memcpy( &infoSetInt[curInterf].ip_addr, 195 &addrs[j], 196 sizeof( addrs[j] ) ); 197 curInterf++; 198 break; 199 } 200 } 201 if ( NT_SUCCESS(status) ) 202 tdiFreeThingSet(addrs); 203 } 204 } 205 } 206 207 tdiFreeThingSet(entIDSet); 208 209 if (NT_SUCCESS(status)) { 210 *infoSet = infoSetInt; 211 *numInterfaces = curInterf; 212 } else { 213 HeapFree(GetProcessHeap(), 0, infoSetInt); 214 } 215 216 return status; 217 } else { 218 tdiFreeThingSet(entIDSet); 219 return STATUS_INSUFFICIENT_RESOURCES; 220 } 221 } 222 223 static DWORD getNumInterfacesInt(BOOL onlyNonLoopback) 224 { 225 DWORD numEntities, numInterfaces = 0; 226 TDIEntityID *entitySet; 227 HANDLE tcpFile; 228 NTSTATUS status; 229 int i; 230 231 status = openTcpFile( &tcpFile, FILE_READ_DATA ); 232 233 if( !NT_SUCCESS(status) ) { 234 WARN("getNumInterfaces: failed %08x\n", status ); 235 return 0; 236 } 237 238 status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); 239 240 if( !NT_SUCCESS(status) ) { 241 WARN("getNumInterfaces: failed %08x\n", status ); 242 closeTcpFile( tcpFile ); 243 return 0; 244 } 245 246 for( i = 0; i < numEntities; i++ ) { 247 if( isInterface( &entitySet[i] ) && 248 (!onlyNonLoopback || 249 (onlyNonLoopback && !isLoopback( tcpFile, &entitySet[i] ))) ) 250 numInterfaces++; 251 } 252 253 TRACE("getNumInterfaces: success: %d %d %08x\n", 254 onlyNonLoopback, numInterfaces, status ); 255 256 closeTcpFile( tcpFile ); 257 258 tdiFreeThingSet( entitySet ); 259 260 return numInterfaces; 261 } 262 263 DWORD getNumInterfaces(void) 264 { 265 return getNumInterfacesInt( FALSE ); 266 } 267 268 DWORD getNumNonLoopbackInterfaces(void) 269 { 270 return getNumInterfacesInt( TRUE ); 271 } 272 273 DWORD getNthInterfaceEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) { 274 DWORD numEntities = 0; 275 DWORD numInterfaces = 0; 276 TDIEntityID *entitySet = 0; 277 NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); 278 int i; 279 280 if( !NT_SUCCESS(status) ) 281 return status; 282 283 for( i = 0; i < numEntities; i++ ) { 284 if( isInterface( &entitySet[i] ) ) { 285 if( numInterfaces == index ) break; 286 else numInterfaces++; 287 } 288 } 289 290 TRACE("Index %d is entity #%d - %04x:%08x\n", index, i, 291 entitySet[i].tei_entity, entitySet[i].tei_instance ); 292 293 if( numInterfaces == index && i < numEntities ) { 294 memcpy( ent, &entitySet[i], sizeof(*ent) ); 295 tdiFreeThingSet( entitySet ); 296 return STATUS_SUCCESS; 297 } else { 298 tdiFreeThingSet( entitySet ); 299 return STATUS_UNSUCCESSFUL; 300 } 301 } 302 303 NTSTATUS getInterfaceInfoByIndex( HANDLE tcpFile, DWORD index, IFInfo *info ) { 304 IFInfo *ifInfo; 305 DWORD numInterfaces; 306 NTSTATUS status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces ); 307 int i; 308 309 if( NT_SUCCESS(status) ) 310 { 311 for( i = 0; i < numInterfaces; i++ ) { 312 if( ifInfo[i].if_info.ent.if_index == index ) { 313 memcpy( info, &ifInfo[i], sizeof(*info) ); 314 break; 315 } 316 } 317 318 HeapFree(GetProcessHeap(), 0, ifInfo); 319 320 return i < numInterfaces ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 321 } 322 323 return status; 324 } 325 326 NTSTATUS getInterfaceInfoByName( HANDLE tcpFile, char *name, IFInfo *info ) { 327 IFInfo *ifInfo; 328 DWORD numInterfaces; 329 int i; 330 NTSTATUS status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces ); 331 332 if( NT_SUCCESS(status) ) 333 { 334 for( i = 0; i < numInterfaces; i++ ) { 335 if( !strcmp((PCHAR)ifInfo[i].if_info.ent.if_descr, name) ) { 336 memcpy( info, &ifInfo[i], sizeof(*info) ); 337 break; 338 } 339 } 340 341 HeapFree(GetProcessHeap(), 0,ifInfo); 342 343 return i < numInterfaces ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 344 } 345 346 return status; 347 } 348 349 /* Note that the result of this operation must be freed later */ 350 351 const char *getInterfaceNameByIndex(DWORD index) 352 { 353 IFInfo ifInfo; 354 HANDLE tcpFile; 355 char *interfaceName = 0, *adapter_name = 0; 356 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 357 358 if( NT_SUCCESS(status) ) { 359 status = getInterfaceInfoByIndex( tcpFile, index, &ifInfo ); 360 361 if( NT_SUCCESS(status) ) { 362 adapter_name = (char *)ifInfo.if_info.ent.if_descr; 363 364 interfaceName = HeapAlloc( GetProcessHeap(), 0, 365 strlen(adapter_name) + 1 ); 366 if (!interfaceName) return NULL; 367 368 strcpy( interfaceName, adapter_name ); 369 } 370 371 closeTcpFile( tcpFile ); 372 } 373 374 return interfaceName; 375 } 376 377 void consumeInterfaceName(const char *name) { 378 HeapFree( GetProcessHeap(), 0, (char *)name ); 379 } 380 381 DWORD getInterfaceIndexByName(const char *name, PDWORD index) 382 { 383 IFInfo ifInfo; 384 HANDLE tcpFile; 385 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 386 387 if( NT_SUCCESS(status) ) { 388 status = getInterfaceInfoByName( tcpFile, (char *)name, &ifInfo ); 389 390 if( NT_SUCCESS(status) ) { 391 *index = ifInfo.if_info.ent.if_index; 392 } 393 394 closeTcpFile( tcpFile ); 395 } 396 397 return status; 398 } 399 400 InterfaceIndexTable *getInterfaceIndexTableInt( BOOL nonLoopbackOnly ) { 401 DWORD numInterfaces, curInterface = 0; 402 int i; 403 IFInfo *ifInfo; 404 InterfaceIndexTable *ret = 0; 405 HANDLE tcpFile; 406 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 407 408 if( NT_SUCCESS(status) ) { 409 status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces ); 410 411 TRACE("InterfaceInfoSet: %08x, %04x:%08x\n", 412 status, 413 ifInfo->entity_id.tei_entity, 414 ifInfo->entity_id.tei_instance); 415 416 if( NT_SUCCESS(status) ) { 417 ret = (InterfaceIndexTable *) 418 calloc(1, 419 sizeof(InterfaceIndexTable) + 420 (numInterfaces - 1) * sizeof(DWORD)); 421 422 if (ret) { 423 ret->numAllocated = numInterfaces; 424 TRACE("NumInterfaces = %d\n", numInterfaces); 425 426 for( i = 0; i < numInterfaces; i++ ) { 427 TRACE("Examining interface %d\n", i); 428 if( !nonLoopbackOnly || 429 !isLoopback( tcpFile, &ifInfo[i].entity_id ) ) { 430 TRACE("Interface %d matches (%d)\n", i, curInterface); 431 ret->indexes[curInterface++] = 432 ifInfo[i].if_info.ent.if_index; 433 } 434 } 435 436 ret->numIndexes = curInterface; 437 } 438 439 tdiFreeThingSet( ifInfo ); 440 } 441 closeTcpFile( tcpFile ); 442 } 443 444 return ret; 445 } 446 447 InterfaceIndexTable *getInterfaceIndexTable(void) { 448 return getInterfaceIndexTableInt( FALSE ); 449 } 450 451 InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void) { 452 return getInterfaceIndexTableInt( TRUE ); 453 } 454 455 DWORD getInterfaceIPAddrByName(const char *name) 456 { 457 return INADDR_ANY; 458 } 459 460 NTSTATUS getIPAddrEntryForIf(HANDLE tcpFile, 461 char *name, 462 DWORD index, 463 IFInfo *ifInfo) { 464 NTSTATUS status = 465 name ? 466 getInterfaceInfoByName( tcpFile, name, ifInfo ) : 467 getInterfaceInfoByIndex( tcpFile, index, ifInfo ); 468 469 if (!NT_SUCCESS(status)) { 470 ERR("getIPAddrEntryForIf returning %lx\n", status); 471 } 472 473 return status; 474 } 475 476 DWORD getAddrByIndexOrName( char *name, DWORD index, IPHLPAddrType addrType ) { 477 IFInfo ifInfo; 478 HANDLE tcpFile; 479 NTSTATUS status = STATUS_SUCCESS; 480 DWORD addrOut = INADDR_ANY; 481 482 status = openTcpFile( &tcpFile, FILE_READ_DATA ); 483 484 if( NT_SUCCESS(status) ) { 485 status = getIPAddrEntryForIf( tcpFile, name, index, &ifInfo ); 486 if( NT_SUCCESS(status) ) { 487 switch( addrType ) { 488 case IPAAddr: addrOut = ifInfo.ip_addr.iae_addr; break; 489 case IPABcast: addrOut = ifInfo.ip_addr.iae_bcastaddr; break; 490 case IPAMask: addrOut = ifInfo.ip_addr.iae_mask; break; 491 case IFMtu: addrOut = ifInfo.if_info.ent.if_mtu; break; 492 case IFStatus: addrOut = ifInfo.if_info.ent.if_operstatus; break; 493 } 494 } 495 closeTcpFile( tcpFile ); 496 } 497 498 return addrOut; 499 } 500 501 DWORD getInterfaceIPAddrByIndex(DWORD index) { 502 return getAddrByIndexOrName( 0, index, IPAAddr ); 503 } 504 505 DWORD getInterfaceBCastAddrByName(const char *name) { 506 return getAddrByIndexOrName( (char *)name, 0, IPABcast ); 507 } 508 509 DWORD getInterfaceBCastAddrByIndex(DWORD index) { 510 return getAddrByIndexOrName( 0, index, IPABcast ); 511 } 512 513 DWORD getInterfaceMaskByName(const char *name) { 514 return getAddrByIndexOrName( (char *)name, 0, IPAMask ); 515 } 516 517 DWORD getInterfaceMaskByIndex(DWORD index) { 518 return getAddrByIndexOrName( 0, index, IPAMask ); 519 } 520 521 void getInterfacePhysicalFromInfo( IFInfo *info, 522 PDWORD len, PBYTE addr, PDWORD type ) { 523 *len = info->if_info.ent.if_physaddrlen; 524 memcpy( addr, info->if_info.ent.if_physaddr, *len ); 525 *type = info->if_info.ent.if_type; 526 } 527 528 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr, 529 PDWORD type) 530 { 531 HANDLE tcpFile; 532 IFInfo info; 533 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 534 535 if( NT_SUCCESS(status) ) { 536 status = getInterfaceInfoByName( tcpFile, (char *)name, &info ); 537 if( NT_SUCCESS(status) ) 538 getInterfacePhysicalFromInfo( &info, len, addr, type ); 539 closeTcpFile( tcpFile ); 540 } 541 542 return status; 543 } 544 545 DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr, 546 PDWORD type) 547 { 548 HANDLE tcpFile; 549 IFInfo info; 550 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 551 552 if( NT_SUCCESS(status) ) { 553 status = getInterfaceInfoByIndex( tcpFile, index, &info ); 554 if( NT_SUCCESS(status) ) 555 getInterfacePhysicalFromInfo( &info, len, addr, type ); 556 closeTcpFile( tcpFile ); 557 } 558 559 return status; 560 } 561 562 DWORD getInterfaceMtuByName(const char *name, PDWORD mtu) { 563 *mtu = getAddrByIndexOrName( (char *)name, 0, IFMtu ); 564 return STATUS_SUCCESS; 565 } 566 567 DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu) { 568 *mtu = getAddrByIndexOrName( 0, index, IFMtu ); 569 return STATUS_SUCCESS; 570 } 571 572 DWORD getInterfaceStatusByName(const char *name, PDWORD status) { 573 *status = getAddrByIndexOrName( (char *)name, 0, IFStatus ); 574 return STATUS_SUCCESS; 575 } 576 577 DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status) 578 { 579 *status = getAddrByIndexOrName( 0, index, IFStatus ); 580 return STATUS_SUCCESS; 581 } 582 583 DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry) 584 { 585 HANDLE tcpFile; 586 IFInfo info; 587 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 588 589 TRACE("Called.\n"); 590 591 if( NT_SUCCESS(status) ) { 592 status = getInterfaceInfoByName( tcpFile, (char *)name, &info ); 593 594 if( NT_SUCCESS(status) ) { 595 memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN], 596 &info.if_info, 597 sizeof(info.if_info) ); 598 } 599 600 TRACE("entry->bDescr = %s\n", entry->bDescr); 601 602 closeTcpFile( tcpFile ); 603 } 604 605 return status; 606 } 607 608 DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry) 609 { 610 HANDLE tcpFile; 611 IFInfo info; 612 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 613 614 TRACE("Called.\n"); 615 616 if( NT_SUCCESS(status) ) { 617 status = getInterfaceInfoByIndex( tcpFile, index, &info ); 618 619 if( NT_SUCCESS(status) ) { 620 memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN], 621 &info.if_info, 622 sizeof(info.if_info) ); 623 } 624 625 closeTcpFile( tcpFile ); 626 } 627 628 return status; 629 } 630 631 char *toIPAddressString(unsigned int addr, char string[16]) 632 { 633 struct in_addr iAddr; 634 635 iAddr.s_addr = addr; 636 637 if (string) 638 strncpy(string, inet_ntoa(iAddr), 16); 639 640 return inet_ntoa(iAddr); 641 } 642 643 NTSTATUS addIPAddress( IPAddr Address, IPMask Mask, DWORD IfIndex, 644 PULONG NteContext, PULONG NteInstance ) 645 { 646 HANDLE tcpFile; 647 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ); 648 IP_SET_DATA Data; 649 IO_STATUS_BLOCK Iosb; 650 651 TRACE("Called.\n"); 652 653 if( !NT_SUCCESS(status) ) return status; 654 655 Data.NteContext = IfIndex; 656 Data.NewAddress = Address; 657 Data.NewNetmask = Mask; 658 659 status = NtDeviceIoControlFile( tcpFile, 660 NULL, 661 NULL, 662 NULL, 663 &Iosb, 664 IOCTL_SET_IP_ADDRESS, 665 &Data, 666 sizeof(Data), 667 &Data, 668 sizeof(Data) ); 669 670 closeTcpFile( tcpFile ); 671 672 if( NT_SUCCESS(status) ) { 673 *NteContext = Iosb.Information; 674 *NteInstance = Data.NewAddress; 675 } 676 677 if (!NT_SUCCESS(status)) { 678 ERR("addIPAddress for if %d returning 0x%lx\n", IfIndex, status); 679 } 680 681 return status; 682 683 } 684 685 NTSTATUS deleteIpAddress( ULONG NteContext ) 686 { 687 HANDLE tcpFile; 688 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ); 689 IO_STATUS_BLOCK Iosb; 690 691 TRACE("Called.\n"); 692 693 if( !NT_SUCCESS(status) ) return status; 694 695 status = NtDeviceIoControlFile( tcpFile, 696 NULL, 697 NULL, 698 NULL, 699 &Iosb, 700 IOCTL_DELETE_IP_ADDRESS, 701 &NteContext, 702 sizeof(USHORT), 703 NULL, 704 0 ); 705 706 closeTcpFile( tcpFile ); 707 708 if (!NT_SUCCESS(status)) { 709 ERR("deleteIpAddress(%lu) returning 0x%lx\n", NteContext, status); 710 } 711 712 return status; 713 } 714