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_descrlen, 108 entry->ent.if_descr); 109 TRACE("} status %08x\n",status); 110 111 return STATUS_SUCCESS; 112 } 113 114 BOOL isInterface( TDIEntityID *if_maybe ) { 115 return 116 if_maybe->tei_entity == IF_ENTITY; 117 } 118 119 BOOL isLoopback( HANDLE tcpFile, TDIEntityID *loop_maybe ) { 120 IFEntrySafelySized entryInfo; 121 NTSTATUS status; 122 123 status = tdiGetMibForIfEntity( tcpFile, 124 loop_maybe, 125 &entryInfo ); 126 127 return NT_SUCCESS(status) && 128 (entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK); 129 } 130 131 BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) { 132 TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT; 133 NTSTATUS status = STATUS_SUCCESS; 134 DWORD returnSize, type; 135 136 req.ID.toi_class = INFO_CLASS_GENERIC; 137 req.ID.toi_type = INFO_TYPE_PROVIDER; 138 req.ID.toi_id = ENTITY_TYPE_ID; 139 req.ID.toi_entity.tei_entity = AT_ENTITY; 140 req.ID.toi_entity.tei_instance = arp_maybe->tei_instance; 141 142 status = DeviceIoControl( tcpFile, 143 IOCTL_TCP_QUERY_INFORMATION_EX, 144 &req, 145 sizeof(req), 146 &type, 147 sizeof(type), 148 &returnSize, 149 NULL ); 150 if( !NT_SUCCESS(status) ) return FALSE; 151 152 return (type & AT_ARP); 153 } 154 155 static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile, 156 IFInfo **infoSet, 157 PDWORD numInterfaces ) { 158 DWORD numEntities; 159 TDIEntityID *entIDSet = NULL; 160 NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entIDSet, &numEntities ); 161 IFInfo *infoSetInt = 0; 162 int curInterf = 0, i; 163 164 if (!NT_SUCCESS(status)) { 165 ERR("getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status); 166 return status; 167 } 168 169 infoSetInt = HeapAlloc( GetProcessHeap(), 0, 170 sizeof(IFInfo) * numEntities ); 171 172 if( infoSetInt ) { 173 for( i = 0; i < numEntities; i++ ) { 174 if( isInterface( &entIDSet[i] ) ) { 175 infoSetInt[curInterf].entity_id = entIDSet[i]; 176 status = tdiGetMibForIfEntity 177 ( tcpFile, 178 &entIDSet[i], 179 &infoSetInt[curInterf].if_info ); 180 TRACE("tdiGetMibForIfEntity: %08x\n", status); 181 if( NT_SUCCESS(status) ) { 182 DWORD numAddrs; 183 IPAddrEntry *addrs; 184 TDIEntityID ip_ent; 185 int j; 186 187 status = getNthIpEntity( tcpFile, curInterf, &ip_ent ); 188 if( NT_SUCCESS(status) ) 189 status = tdiGetIpAddrsForIpEntity 190 ( tcpFile, &ip_ent, &addrs, &numAddrs ); 191 for( j = 0; NT_SUCCESS(status) && j < numAddrs; j++ ) { 192 TRACE("ADDR %d: index %d (target %d)\n", j, addrs[j].iae_index, infoSetInt[curInterf].if_info.ent.if_index); 193 if( addrs[j].iae_index == 194 infoSetInt[curInterf].if_info.ent.if_index ) { 195 memcpy( &infoSetInt[curInterf].ip_addr, 196 &addrs[j], 197 sizeof( addrs[j] ) ); 198 curInterf++; 199 break; 200 } 201 } 202 if ( NT_SUCCESS(status) ) 203 tdiFreeThingSet(addrs); 204 } 205 } 206 } 207 208 tdiFreeThingSet(entIDSet); 209 210 if (NT_SUCCESS(status)) { 211 *infoSet = infoSetInt; 212 *numInterfaces = curInterf; 213 } else { 214 HeapFree(GetProcessHeap(), 0, infoSetInt); 215 } 216 217 return status; 218 } else { 219 tdiFreeThingSet(entIDSet); 220 return STATUS_INSUFFICIENT_RESOURCES; 221 } 222 } 223 224 static DWORD getNumInterfacesInt(BOOL onlyNonLoopback) 225 { 226 DWORD numEntities, numInterfaces = 0; 227 TDIEntityID *entitySet; 228 HANDLE tcpFile; 229 NTSTATUS status; 230 int i; 231 232 status = openTcpFile( &tcpFile, FILE_READ_DATA ); 233 234 if( !NT_SUCCESS(status) ) { 235 WARN("getNumInterfaces: failed %08x\n", status ); 236 return 0; 237 } 238 239 status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); 240 241 if( !NT_SUCCESS(status) ) { 242 WARN("getNumInterfaces: failed %08x\n", status ); 243 closeTcpFile( tcpFile ); 244 return 0; 245 } 246 247 for( i = 0; i < numEntities; i++ ) { 248 if( isInterface( &entitySet[i] ) && 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( !strncmp((PCHAR)ifInfo[i].if_info.ent.if_descr, name, ifInfo[i].if_info.ent.if_descrlen) ) { 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 = NULL; 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 interfaceName = HeapAlloc( GetProcessHeap(), 0, 363 ifInfo.if_info.ent.if_descrlen + 1 ); 364 if( interfaceName ) { 365 memcpy(interfaceName, ifInfo.if_info.ent.if_descr, ifInfo.if_info.ent.if_descrlen); 366 interfaceName[ifInfo.if_info.ent.if_descrlen] = '\0'; 367 } 368 } 369 370 closeTcpFile( tcpFile ); 371 } 372 373 return interfaceName; 374 } 375 376 void consumeInterfaceName(const char *name) { 377 HeapFree( GetProcessHeap(), 0, (char *)name ); 378 } 379 380 DWORD getInterfaceIndexByName(const char *name, PDWORD index) 381 { 382 IFInfo ifInfo; 383 HANDLE tcpFile; 384 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 385 386 if( NT_SUCCESS(status) ) { 387 status = getInterfaceInfoByName( tcpFile, (char *)name, &ifInfo ); 388 389 if( NT_SUCCESS(status) ) { 390 *index = ifInfo.if_info.ent.if_index; 391 } 392 393 closeTcpFile( tcpFile ); 394 } 395 396 return status; 397 } 398 399 InterfaceIndexTable *getInterfaceIndexTableInt( BOOL nonLoopbackOnly ) { 400 DWORD numInterfaces, curInterface = 0; 401 int i; 402 IFInfo *ifInfo; 403 InterfaceIndexTable *ret = 0; 404 HANDLE tcpFile; 405 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 406 407 if( NT_SUCCESS(status) ) { 408 status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces ); 409 410 TRACE("InterfaceInfoSet: %08x, %04x:%08x\n", 411 status, 412 ifInfo->entity_id.tei_entity, 413 ifInfo->entity_id.tei_instance); 414 415 if( NT_SUCCESS(status) ) { 416 ret = (InterfaceIndexTable *) 417 calloc(1, 418 sizeof(InterfaceIndexTable) + 419 (numInterfaces - 1) * sizeof(DWORD)); 420 421 if (ret) { 422 ret->numAllocated = numInterfaces; 423 TRACE("NumInterfaces = %d\n", numInterfaces); 424 425 for( i = 0; i < numInterfaces; i++ ) { 426 TRACE("Examining interface %d\n", i); 427 if( !nonLoopbackOnly || 428 !isLoopback( tcpFile, &ifInfo[i].entity_id ) ) { 429 TRACE("Interface %d matches (%d)\n", i, curInterface); 430 ret->indexes[curInterface++] = 431 ifInfo[i].if_info.ent.if_index; 432 } 433 } 434 435 ret->numIndexes = curInterface; 436 } 437 438 tdiFreeThingSet( ifInfo ); 439 } 440 closeTcpFile( tcpFile ); 441 } 442 443 return ret; 444 } 445 446 InterfaceIndexTable *getInterfaceIndexTable(void) { 447 return getInterfaceIndexTableInt( FALSE ); 448 } 449 450 InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void) { 451 return getInterfaceIndexTableInt( TRUE ); 452 } 453 454 DWORD getInterfaceIPAddrByName(const char *name) 455 { 456 return INADDR_ANY; 457 } 458 459 NTSTATUS getIPAddrEntryForIf(HANDLE tcpFile, 460 char *name, 461 DWORD index, 462 IFInfo *ifInfo) { 463 NTSTATUS status = 464 name ? 465 getInterfaceInfoByName( tcpFile, name, ifInfo ) : 466 getInterfaceInfoByIndex( tcpFile, index, ifInfo ); 467 468 if (!NT_SUCCESS(status)) { 469 ERR("getIPAddrEntryForIf returning %lx\n", status); 470 } 471 472 return status; 473 } 474 475 DWORD getAddrByIndexOrName( char *name, DWORD index, IPHLPAddrType addrType ) { 476 IFInfo ifInfo; 477 HANDLE tcpFile; 478 NTSTATUS status = STATUS_SUCCESS; 479 DWORD addrOut = INADDR_ANY; 480 481 status = openTcpFile( &tcpFile, FILE_READ_DATA ); 482 483 if( NT_SUCCESS(status) ) { 484 status = getIPAddrEntryForIf( tcpFile, name, index, &ifInfo ); 485 if( NT_SUCCESS(status) ) { 486 switch( addrType ) { 487 case IPAAddr: addrOut = ifInfo.ip_addr.iae_addr; break; 488 case IPABcast: addrOut = ifInfo.ip_addr.iae_bcastaddr; break; 489 case IPAMask: addrOut = ifInfo.ip_addr.iae_mask; break; 490 case IFMtu: addrOut = ifInfo.if_info.ent.if_mtu; break; 491 case IFStatus: addrOut = ifInfo.if_info.ent.if_operstatus; break; 492 } 493 } 494 closeTcpFile( tcpFile ); 495 } 496 497 return addrOut; 498 } 499 500 DWORD getInterfaceIPAddrByIndex(DWORD index) { 501 return getAddrByIndexOrName( 0, index, IPAAddr ); 502 } 503 504 DWORD getInterfaceBCastAddrByName(const char *name) { 505 return getAddrByIndexOrName( (char *)name, 0, IPABcast ); 506 } 507 508 DWORD getInterfaceBCastAddrByIndex(DWORD index) { 509 return getAddrByIndexOrName( 0, index, IPABcast ); 510 } 511 512 DWORD getInterfaceMaskByName(const char *name) { 513 return getAddrByIndexOrName( (char *)name, 0, IPAMask ); 514 } 515 516 DWORD getInterfaceMaskByIndex(DWORD index) { 517 return getAddrByIndexOrName( 0, index, IPAMask ); 518 } 519 520 void getInterfacePhysicalFromInfo( IFInfo *info, 521 PDWORD len, PBYTE addr, PDWORD type ) { 522 *len = info->if_info.ent.if_physaddrlen; 523 memcpy( addr, info->if_info.ent.if_physaddr, *len ); 524 *type = info->if_info.ent.if_type; 525 } 526 527 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr, 528 PDWORD type) 529 { 530 HANDLE tcpFile; 531 IFInfo info; 532 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 533 534 if( NT_SUCCESS(status) ) { 535 status = getInterfaceInfoByName( tcpFile, (char *)name, &info ); 536 if( NT_SUCCESS(status) ) 537 getInterfacePhysicalFromInfo( &info, len, addr, type ); 538 closeTcpFile( tcpFile ); 539 } 540 541 return status; 542 } 543 544 DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr, 545 PDWORD type) 546 { 547 HANDLE tcpFile; 548 IFInfo info; 549 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 550 551 if( NT_SUCCESS(status) ) { 552 status = getInterfaceInfoByIndex( tcpFile, index, &info ); 553 if( NT_SUCCESS(status) ) 554 getInterfacePhysicalFromInfo( &info, len, addr, type ); 555 closeTcpFile( tcpFile ); 556 } 557 558 return status; 559 } 560 561 DWORD getInterfaceMtuByName(const char *name, PDWORD mtu) { 562 *mtu = getAddrByIndexOrName( (char *)name, 0, IFMtu ); 563 return STATUS_SUCCESS; 564 } 565 566 DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu) { 567 *mtu = getAddrByIndexOrName( 0, index, IFMtu ); 568 return STATUS_SUCCESS; 569 } 570 571 DWORD getInterfaceStatusByName(const char *name, PDWORD status) { 572 *status = getAddrByIndexOrName( (char *)name, 0, IFStatus ); 573 return STATUS_SUCCESS; 574 } 575 576 DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status) 577 { 578 *status = getAddrByIndexOrName( 0, index, IFStatus ); 579 return STATUS_SUCCESS; 580 } 581 582 DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry) 583 { 584 HANDLE tcpFile; 585 IFInfo info; 586 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 587 588 TRACE("Called.\n"); 589 590 if( NT_SUCCESS(status) ) { 591 status = getInterfaceInfoByName( tcpFile, (char *)name, &info ); 592 593 if( NT_SUCCESS(status) ) { 594 memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN], 595 &info.if_info, 596 sizeof(info.if_info) ); 597 } 598 599 TRACE("entry->bDescr = %s\n", entry->bDescr); 600 601 closeTcpFile( tcpFile ); 602 } 603 604 return status; 605 } 606 607 DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry) 608 { 609 HANDLE tcpFile; 610 IFInfo info; 611 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); 612 613 TRACE("Called.\n"); 614 615 if( NT_SUCCESS(status) ) { 616 status = getInterfaceInfoByIndex( tcpFile, index, &info ); 617 618 if( NT_SUCCESS(status) ) { 619 memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN], 620 &info.if_info, 621 sizeof(info.if_info) ); 622 } 623 624 closeTcpFile( tcpFile ); 625 } 626 627 return status; 628 } 629 630 char *toIPAddressString(unsigned int addr, char string[16]) 631 { 632 struct in_addr iAddr; 633 634 iAddr.s_addr = addr; 635 636 if (string) 637 strncpy(string, inet_ntoa(iAddr), 16); 638 639 return inet_ntoa(iAddr); 640 } 641 642 NTSTATUS addIPAddress( IPAddr Address, IPMask Mask, DWORD IfIndex, 643 PULONG NteContext, PULONG NteInstance ) 644 { 645 HANDLE tcpFile; 646 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ); 647 IP_SET_DATA Data; 648 IO_STATUS_BLOCK Iosb; 649 650 TRACE("Called.\n"); 651 652 if( !NT_SUCCESS(status) ) return status; 653 654 Data.NteContext = IfIndex; 655 Data.NewAddress = Address; 656 Data.NewNetmask = Mask; 657 658 status = NtDeviceIoControlFile( tcpFile, 659 NULL, 660 NULL, 661 NULL, 662 &Iosb, 663 IOCTL_SET_IP_ADDRESS, 664 &Data, 665 sizeof(Data), 666 &Data, 667 sizeof(Data) ); 668 669 closeTcpFile( tcpFile ); 670 671 if( NT_SUCCESS(status) ) { 672 *NteContext = Iosb.Information; 673 *NteInstance = Data.NewAddress; 674 } 675 676 if (!NT_SUCCESS(status)) { 677 ERR("addIPAddress for if %d returning 0x%lx\n", IfIndex, status); 678 } 679 680 return status; 681 682 } 683 684 NTSTATUS deleteIpAddress( ULONG NteContext ) 685 { 686 HANDLE tcpFile; 687 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ); 688 IO_STATUS_BLOCK Iosb; 689 690 TRACE("Called.\n"); 691 692 if( !NT_SUCCESS(status) ) return status; 693 694 status = NtDeviceIoControlFile( tcpFile, 695 NULL, 696 NULL, 697 NULL, 698 &Iosb, 699 IOCTL_DELETE_IP_ADDRESS, 700 &NteContext, 701 sizeof(USHORT), 702 NULL, 703 0 ); 704 705 closeTcpFile( tcpFile ); 706 707 if (!NT_SUCCESS(status)) { 708 ERR("deleteIpAddress(%lu) returning 0x%lx\n", NteContext, status); 709 } 710 711 return status; 712 } 713