[CRT] Massively improve performance of rand_s
[reactos.git] / dll / win32 / iphlpapi / ifenum_reactos.c
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 ||
250 (onlyNonLoopback && !isLoopback( tcpFile, &entitySet[i] ))) )
251 numInterfaces++;
252 }
253
254 TRACE("getNumInterfaces: success: %d %d %08x\n",
255 onlyNonLoopback, numInterfaces, status );
256
257 closeTcpFile( tcpFile );
258
259 tdiFreeThingSet( entitySet );
260
261 return numInterfaces;
262 }
263
264 DWORD getNumInterfaces(void)
265 {
266 return getNumInterfacesInt( FALSE );
267 }
268
269 DWORD getNumNonLoopbackInterfaces(void)
270 {
271 return getNumInterfacesInt( TRUE );
272 }
273
274 DWORD getNthInterfaceEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) {
275 DWORD numEntities = 0;
276 DWORD numInterfaces = 0;
277 TDIEntityID *entitySet = 0;
278 NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
279 int i;
280
281 if( !NT_SUCCESS(status) )
282 return status;
283
284 for( i = 0; i < numEntities; i++ ) {
285 if( isInterface( &entitySet[i] ) ) {
286 if( numInterfaces == index ) break;
287 else numInterfaces++;
288 }
289 }
290
291 TRACE("Index %d is entity #%d - %04x:%08x\n", index, i,
292 entitySet[i].tei_entity, entitySet[i].tei_instance );
293
294 if( numInterfaces == index && i < numEntities ) {
295 memcpy( ent, &entitySet[i], sizeof(*ent) );
296 tdiFreeThingSet( entitySet );
297 return STATUS_SUCCESS;
298 } else {
299 tdiFreeThingSet( entitySet );
300 return STATUS_UNSUCCESSFUL;
301 }
302 }
303
304 NTSTATUS getInterfaceInfoByIndex( HANDLE tcpFile, DWORD index, IFInfo *info ) {
305 IFInfo *ifInfo;
306 DWORD numInterfaces;
307 NTSTATUS status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces );
308 int i;
309
310 if( NT_SUCCESS(status) )
311 {
312 for( i = 0; i < numInterfaces; i++ ) {
313 if( ifInfo[i].if_info.ent.if_index == index ) {
314 memcpy( info, &ifInfo[i], sizeof(*info) );
315 break;
316 }
317 }
318
319 HeapFree(GetProcessHeap(), 0, ifInfo);
320
321 return i < numInterfaces ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
322 }
323
324 return status;
325 }
326
327 NTSTATUS getInterfaceInfoByName( HANDLE tcpFile, char *name, IFInfo *info ) {
328 IFInfo *ifInfo;
329 DWORD numInterfaces;
330 int i;
331 NTSTATUS status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces );
332
333 if( NT_SUCCESS(status) )
334 {
335 for( i = 0; i < numInterfaces; i++ ) {
336 if( !strncmp((PCHAR)ifInfo[i].if_info.ent.if_descr, name, ifInfo[i].if_info.ent.if_descrlen) ) {
337 memcpy( info, &ifInfo[i], sizeof(*info) );
338 break;
339 }
340 }
341
342 HeapFree(GetProcessHeap(), 0,ifInfo);
343
344 return i < numInterfaces ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
345 }
346
347 return status;
348 }
349
350 /* Note that the result of this operation must be freed later */
351
352 const char *getInterfaceNameByIndex(DWORD index)
353 {
354 IFInfo ifInfo;
355 HANDLE tcpFile;
356 char *interfaceName = NULL;
357 NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
358
359 if( NT_SUCCESS(status) ) {
360 status = getInterfaceInfoByIndex( tcpFile, index, &ifInfo );
361
362 if( NT_SUCCESS(status) ) {
363 interfaceName = HeapAlloc( GetProcessHeap(), 0,
364 ifInfo.if_info.ent.if_descrlen + 1 );
365 if( interfaceName ) {
366 memcpy(interfaceName, ifInfo.if_info.ent.if_descr, ifInfo.if_info.ent.if_descrlen);
367 interfaceName[ifInfo.if_info.ent.if_descrlen] = '\0';
368 }
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 }