7c6a20f3683ef2014db4e40463c0e6e505c14065
[reactos.git] / reactos / lib / iphlpapi / iphlpapi_main.c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "config.h"
22 #include "iphlpapi_private.h"
23
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #ifdef HAVE_NETINET_IN_H
28 # include <netinet/in.h>
29 #endif
30 #ifdef HAVE_ARPA_INET_H
31 # include <arpa/inet.h>
32 #endif
33 #ifdef HAVE_ARPA_NAMESER_H
34 # include <arpa/nameser.h>
35 #endif
36 #ifdef HAVE_RESOLV_H
37 # include <resolv.h>
38 #endif
39
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winreg.h"
44 #include "iphlpapi.h"
45 #include "ifenum.h"
46 #include "ipstats.h"
47 #include "resinfo.h"
48 #include "route.h"
49 #include "wine/debug.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
52
53 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
54 {
55 switch (fdwReason) {
56 case DLL_PROCESS_ATTACH:
57 DisableThreadLibraryCalls( hinstDLL );
58 interfaceMapInit();
59 break;
60
61 case DLL_PROCESS_DETACH:
62 interfaceMapFree();
63 break;
64 }
65 return TRUE;
66 }
67
68 /******************************************************************
69 * AddIPAddress (IPHLPAPI.@)
70 *
71 *
72 * PARAMS
73 *
74 * Address [In]
75 * IpMask [In]
76 * IfIndex [In]
77 * NTEContext [In/Out]
78 * NTEInstance [In/Out]
79 *
80 * RETURNS
81 *
82 * DWORD
83 *
84 */
85 DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance)
86 {
87 return addIPAddress( Address, Netmask, IfIndex, NteContext, NteInstance );
88 }
89
90
91 /******************************************************************
92 * AllocateAndGetIfTableFromStack (IPHLPAPI.@)
93 *
94 *
95 * PARAMS
96 *
97 * ppIfTable [Out] -- pointer into which the MIB_IFTABLE is
98 * allocated and returned.
99 * bOrder [In] -- passed to GetIfTable to order the table
100 * heap [In] -- heap from which the table is allocated
101 * flags [In] -- flags to HeapAlloc
102 *
103 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
104 * GetIfTable returns otherwise
105 *
106 */
107 DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable,
108 BOOL bOrder, HANDLE heap, DWORD flags)
109 {
110 DWORD ret;
111
112 TRACE("ppIfTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n", ppIfTable,
113 (DWORD)bOrder, (DWORD)heap, flags);
114 if (!ppIfTable)
115 ret = ERROR_INVALID_PARAMETER;
116 else {
117 DWORD dwSize = 0;
118
119 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
120 if (ret == ERROR_INSUFFICIENT_BUFFER) {
121 *ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize);
122 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
123 }
124 }
125 TRACE("returning %ld\n", ret);
126 return ret;
127 }
128
129
130 /******************************************************************
131 * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@)
132 *
133 *
134 * PARAMS
135 *
136 * ppIpAddrTable [Out]
137 * bOrder [In] -- passed to GetIpAddrTable to order the table
138 * heap [In] -- heap from which the table is allocated
139 * flags [In] -- flags to HeapAlloc
140 *
141 * RETURNS
142 *
143 * DWORD
144 *
145 */
146 DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
147 BOOL bOrder, HANDLE heap, DWORD flags)
148 {
149 DWORD ret;
150
151 TRACE("ppIpAddrTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
152 ppIpAddrTable, (DWORD)bOrder, (DWORD)heap, flags);
153 if (!ppIpAddrTable)
154 ret = ERROR_INVALID_PARAMETER;
155 else {
156 DWORD dwSize = 0;
157
158 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
159 if (ret == ERROR_INSUFFICIENT_BUFFER) {
160 *ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize);
161 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
162 }
163 }
164 TRACE("returning %ld\n", ret);
165 return ret;
166 }
167
168
169 /******************************************************************
170 * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
171 *
172 *
173 * ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is
174 * allocated and returned.
175 * bOrder [In] -- passed to GetIfTable to order the table
176 * heap [In] -- heap from which the table is allocated
177 * flags [In] -- flags to HeapAlloc
178 *
179 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
180 * GetIpForwardTable returns otherwise
181 *
182 */
183 DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *
184 ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags)
185 {
186 DWORD ret;
187
188 TRACE("ppIpForwardTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
189 ppIpForwardTable, (DWORD)bOrder, (DWORD)heap, flags);
190 if (!ppIpForwardTable)
191 ret = ERROR_INVALID_PARAMETER;
192 else {
193 DWORD dwSize = 0;
194
195 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
196 if (ret == ERROR_INSUFFICIENT_BUFFER) {
197 *ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize);
198 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
199 }
200 }
201 TRACE("returning %ld\n", ret);
202 return ret;
203 }
204
205
206 /******************************************************************
207 * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@)
208 *
209 *
210 * PARAMS
211 *
212 * ppIpNetTable [Out]
213 * bOrder [In] -- passed to GetIpNetTable to order the table
214 * heap [In] -- heap from which the table is allocated
215 * flags [In] -- flags to HeapAlloc
216 *
217 * RETURNS
218 *
219 * DWORD
220 *
221 */
222 DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable,
223 BOOL bOrder, HANDLE heap, DWORD flags)
224 {
225 DWORD ret;
226
227 TRACE("ppIpNetTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
228 ppIpNetTable, (DWORD)bOrder, (DWORD)heap, flags);
229 if (!ppIpNetTable)
230 ret = ERROR_INVALID_PARAMETER;
231 else {
232 DWORD dwSize = 0;
233
234 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
235 if (ret == ERROR_INSUFFICIENT_BUFFER) {
236 *ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize);
237 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
238 }
239 }
240 TRACE("returning %ld\n", ret);
241 return ret;
242 }
243
244
245 /******************************************************************
246 * AllocateAndGetTcpTableFromStack (IPHLPAPI.@)
247 *
248 *
249 * PARAMS
250 *
251 * ppTcpTable [Out]
252 * bOrder [In] -- passed to GetTcpTable to order the table
253 * heap [In] -- heap from which the table is allocated
254 * flags [In] -- flags to HeapAlloc
255 *
256 * RETURNS
257 *
258 * DWORD
259 *
260 */
261 DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
262 BOOL bOrder, HANDLE heap, DWORD flags)
263 {
264 DWORD ret;
265
266 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
267 ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags);
268 if (!ppTcpTable)
269 ret = ERROR_INVALID_PARAMETER;
270 else {
271 DWORD dwSize = 0;
272
273 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
274 if (ret == ERROR_INSUFFICIENT_BUFFER) {
275 *ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize);
276 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
277 }
278 }
279 TRACE("returning %ld\n", ret);
280 return ret;
281 }
282
283
284 /******************************************************************
285 * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
286 *
287 *
288 * PARAMS
289 *
290 * ppUdpTable [Out]
291 * bOrder [In] -- passed to GetUdpTable to order the table
292 * heap [In] -- heap from which the table is allocated
293 * flags [In] -- flags to HeapAlloc
294 *
295 * RETURNS
296 *
297 * DWORD
298 *
299 */
300 DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
301 BOOL bOrder, HANDLE heap, DWORD flags)
302 {
303 DWORD ret;
304
305 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
306 ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags);
307 if (!ppUdpTable)
308 ret = ERROR_INVALID_PARAMETER;
309 else {
310 DWORD dwSize = 0;
311
312 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
313 if (ret == ERROR_INSUFFICIENT_BUFFER) {
314 *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize);
315 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
316 }
317 }
318 TRACE("returning %ld\n", ret);
319 return ret;
320 }
321
322
323 /******************************************************************
324 * CreateIpForwardEntry (IPHLPAPI.@)
325 *
326 *
327 * PARAMS
328 *
329 * pRoute [In/Out]
330 *
331 * RETURNS
332 *
333 * DWORD
334 *
335 */
336 DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
337 {
338 return createIpForwardEntry( pRoute );
339 }
340
341
342 /******************************************************************
343 * CreateIpNetEntry (IPHLPAPI.@)
344 *
345 *
346 * PARAMS
347 *
348 * pArpEntry [In/Out]
349 *
350 * RETURNS
351 *
352 * DWORD
353 *
354 */
355 DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
356 {
357 TRACE("pArpEntry %p\n", pArpEntry);
358 /* could use SIOCSARP on systems that support it, not sure I want to */
359 FIXME(":stub\n");
360 return (DWORD) 0;
361 }
362
363
364 /******************************************************************
365 * CreateProxyArpEntry (IPHLPAPI.@)
366 *
367 *
368 * PARAMS
369 *
370 * dwAddress [In]
371 * dwMask [In]
372 * dwIfIndex [In]
373 *
374 * RETURNS
375 *
376 * DWORD
377 *
378 */
379 DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
380 {
381 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
382 dwMask, dwIfIndex);
383 FIXME(":stub\n");
384 /* marking Win2K+ functions not supported */
385 return ERROR_NOT_SUPPORTED;
386 }
387
388
389 /******************************************************************
390 * DeleteIPAddress (IPHLPAPI.@)
391 *
392 *
393 * PARAMS
394 *
395 * NTEContext [In]
396 *
397 * RETURNS
398 *
399 * DWORD
400 *
401 */
402 DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
403 {
404 TRACE("NTEContext %ld\n", NTEContext);
405 return deleteIpAddress( NTEContext );
406 }
407
408
409 /******************************************************************
410 * DeleteIpForwardEntry (IPHLPAPI.@)
411 *
412 *
413 * PARAMS
414 *
415 * pRoute [In/Out]
416 *
417 * RETURNS
418 *
419 * DWORD
420 *
421 */
422 DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
423 {
424 return deleteIpForwardEntry( pRoute );
425 }
426
427
428 /******************************************************************
429 * DeleteIpNetEntry (IPHLPAPI.@)
430 *
431 *
432 * PARAMS
433 *
434 * pArpEntry [In/Out]
435 *
436 * RETURNS
437 *
438 * DWORD
439 *
440 */
441 DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
442 {
443 TRACE("pArpEntry %p\n", pArpEntry);
444 /* could use SIOCDARP on systems that support it, not sure I want to */
445 FIXME(":stub\n");
446 return (DWORD) 0;
447 }
448
449
450 /******************************************************************
451 * DeleteProxyArpEntry (IPHLPAPI.@)
452 *
453 *
454 * PARAMS
455 *
456 * dwAddress [In]
457 * dwMask [In]
458 * dwIfIndex [In]
459 *
460 * RETURNS
461 *
462 * DWORD
463 *
464 */
465 DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
466 {
467 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
468 dwMask, dwIfIndex);
469 FIXME(":stub\n");
470 /* marking Win2K+ functions not supported */
471 return ERROR_NOT_SUPPORTED;
472 }
473
474 /******************************************************************
475 * EnableRouter (IPHLPAPI.@)
476 *
477 *
478 * PARAMS
479 *
480 * pHandle [In/Out]
481 * pOverlapped [In/Out]
482 *
483 * RETURNS
484 *
485 * DWORD
486 *
487 */
488 DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped)
489 {
490 TRACE("pHandle %p, pOverlapped %p\n", pHandle, pOverlapped);
491 FIXME(":stub\n");
492 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
493 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
494 marking Win2K+ functions not supported */
495 return ERROR_NOT_SUPPORTED;
496 }
497
498
499 /******************************************************************
500 * FlushIpNetTable (IPHLPAPI.@)
501 *
502 *
503 * PARAMS
504 *
505 * dwIfIndex [In]
506 *
507 * RETURNS
508 *
509 * DWORD
510 *
511 */
512 DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex)
513 {
514 TRACE("dwIfIndex 0x%08lx\n", dwIfIndex);
515 FIXME(":stub\n");
516 /* this flushes the arp cache of the given index
517 marking Win2K+ functions not supported */
518 return ERROR_NOT_SUPPORTED;
519 }
520
521
522 /******************************************************************
523 * GetAdapterIndex (IPHLPAPI.@)
524 *
525 *
526 * PARAMS
527 *
528 * AdapterName [In/Out]
529 * IfIndex [In/Out]
530 *
531 * RETURNS
532 *
533 * DWORD
534 *
535 */
536 DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
537 {
538 TRACE("AdapterName %p, IfIndex %p\n", AdapterName, IfIndex);
539 FIXME(":stub\n");
540 /* marking Win2K+ functions not supported */
541 return ERROR_NOT_SUPPORTED;
542 }
543
544
545 /******************************************************************
546 * GetAdaptersInfo (IPHLPAPI.@)
547 *
548 *
549 * PARAMS
550 *
551 * pAdapterInfo [In/Out]
552 * pOutBufLen [In/Out]
553 *
554 * RETURNS
555 *
556 * DWORD
557 *
558 */
559 DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
560 {
561 DWORD ret;
562
563 TRACE("pAdapterInfo %p, pOutBufLen %p\n", pAdapterInfo, pOutBufLen);
564 if (!pOutBufLen)
565 ret = ERROR_INVALID_PARAMETER;
566 else {
567 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
568
569 if (numNonLoopbackInterfaces > 0) {
570 /* this calculation assumes only one address in the IP_ADDR_STRING lists.
571 that's okay, because:
572 - we don't get multiple addresses per adapter anyway
573 - we don't know about per-adapter gateways
574 - DHCP and WINS servers can have max one entry per list */
575 ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces;
576
577 if (!pAdapterInfo || *pOutBufLen < size) {
578 *pOutBufLen = size;
579 ret = ERROR_BUFFER_OVERFLOW;
580 }
581 else {
582 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
583
584 if (table) {
585 size = sizeof(IP_ADAPTER_INFO) * table->numIndexes;
586 if (*pOutBufLen < size) {
587 *pOutBufLen = size;
588 ret = ERROR_INSUFFICIENT_BUFFER;
589 }
590 else {
591 DWORD ndx;
592 HKEY hKey;
593 BOOL winsEnabled = FALSE;
594 IP_ADDRESS_STRING primaryWINS, secondaryWINS;
595
596 memset(pAdapterInfo, 0, size);
597 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
598 "Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ,
599 &hKey) == ERROR_SUCCESS) {
600 DWORD size = sizeof(primaryWINS.String);
601 unsigned long addr;
602
603 RegQueryValueExA(hKey, "WinsServer", NULL, NULL,
604 primaryWINS.String, &size);
605 addr = inet_addr(primaryWINS.String);
606 if (addr != INADDR_NONE && addr != INADDR_ANY)
607 winsEnabled = TRUE;
608 size = sizeof(secondaryWINS.String);
609 RegQueryValueExA(hKey, "BackupWinsServer", NULL, NULL,
610 secondaryWINS.String, &size);
611 addr = inet_addr(secondaryWINS.String);
612 if (addr != INADDR_NONE && addr != INADDR_ANY)
613 winsEnabled = TRUE;
614 RegCloseKey(hKey);
615 }
616 for (ndx = 0; ndx < table->numIndexes; ndx++) {
617 PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
618 DWORD addrLen = sizeof(ptr->Address), type;
619 const char *ifname =
620 getInterfaceNameByIndex(table->indexes[ndx]);
621
622 /* on Win98 this is left empty, but whatever */
623
624 strncpy(ptr->AdapterName,ifname,sizeof(ptr->AdapterName));
625 consumeInterfaceName(ifname);
626 ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0';
627 getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen,
628 ptr->Address, &type);
629 /* MS defines address length and type as UINT in some places and
630 DWORD in others, **sigh**. Don't want to assume that PUINT and
631 PDWORD are equiv (64-bit?) */
632 ptr->AddressLength = addrLen;
633 ptr->Type = type;
634 ptr->Index = table->indexes[ndx];
635 toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]),
636 ptr->IpAddressList.IpAddress.String);
637 toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]),
638 ptr->IpAddressList.IpMask.String);
639 if (winsEnabled) {
640 ptr->HaveWins = TRUE;
641 memcpy(ptr->PrimaryWinsServer.IpAddress.String,
642 primaryWINS.String, sizeof(primaryWINS.String));
643 memcpy(ptr->SecondaryWinsServer.IpAddress.String,
644 secondaryWINS.String, sizeof(secondaryWINS.String));
645 }
646 if (ndx < table->numIndexes - 1)
647 ptr->Next = &pAdapterInfo[ndx + 1];
648 else
649 ptr->Next = NULL;
650 }
651 ret = NO_ERROR;
652 }
653 free(table);
654 }
655 else
656 ret = ERROR_OUTOFMEMORY;
657 }
658 }
659 else
660 ret = ERROR_NO_DATA;
661 }
662 TRACE("returning %ld\n", ret);
663 return ret;
664 }
665
666
667 /******************************************************************
668 * GetBestInterface (IPHLPAPI.@)
669 *
670 *
671 * PARAMS
672 *
673 * dwDestAddr [In]
674 * pdwBestIfIndex [In/Out]
675 *
676 * RETURNS
677 *
678 * DWORD
679 *
680 */
681 DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
682 {
683 DWORD ret;
684
685 TRACE("dwDestAddr 0x%08lx, pdwBestIfIndex %p\n", dwDestAddr, pdwBestIfIndex);
686 if (!pdwBestIfIndex)
687 ret = ERROR_INVALID_PARAMETER;
688 else {
689 MIB_IPFORWARDROW ipRow;
690
691 ret = GetBestRoute(dwDestAddr, 0, &ipRow);
692 if (ret == ERROR_SUCCESS)
693 *pdwBestIfIndex = ipRow.dwForwardIfIndex;
694 }
695 TRACE("returning %ld\n", ret);
696 return ret;
697 }
698
699
700 /******************************************************************
701 * GetBestRoute (IPHLPAPI.@)
702 *
703 *
704 * PARAMS
705 *
706 * dwDestAddr [In]
707 * dwSourceAddr [In]
708 * OUT [In]
709 *
710 * RETURNS
711 *
712 * DWORD
713 *
714 */
715 DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute)
716 {
717 PMIB_IPFORWARDTABLE table;
718 DWORD ret;
719
720 TRACE("dwDestAddr 0x%08lx, dwSourceAddr 0x%08lx, pBestRoute %p\n", dwDestAddr,
721 dwSourceAddr, pBestRoute);
722 if (!pBestRoute)
723 return ERROR_INVALID_PARAMETER;
724
725 AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
726 if (table) {
727 DWORD ndx, matchedBits, matchedNdx = 0;
728
729 for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
730 if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
731 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
732 DWORD numShifts, mask;
733
734 for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
735 mask && !(mask & 1); mask >>= 1, numShifts++)
736 ;
737 if (numShifts > matchedBits) {
738 matchedBits = numShifts;
739 matchedNdx = ndx;
740 }
741 }
742 }
743 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW));
744 HeapFree(GetProcessHeap(), 0, table);
745 ret = ERROR_SUCCESS;
746 }
747 else
748 ret = ERROR_OUTOFMEMORY;
749 TRACE("returning %ld\n", ret);
750 return ret;
751 }
752
753
754 /******************************************************************
755 * GetFriendlyIfIndex (IPHLPAPI.@)
756 *
757 *
758 * PARAMS
759 *
760 * IfIndex [In]
761 *
762 * RETURNS
763 *
764 * DWORD
765 *
766 */
767 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
768 {
769 /* windows doesn't validate these, either, just makes sure the top byte is
770 cleared. I assume my ifenum module never gives an index with the top
771 byte set. */
772 TRACE("returning %ld\n", IfIndex);
773 return IfIndex;
774 }
775
776
777 /******************************************************************
778 * GetIcmpStatistics (IPHLPAPI.@)
779 *
780 *
781 * PARAMS
782 *
783 * pStats [In/Out]
784 *
785 * RETURNS
786 *
787 * DWORD
788 *
789 */
790 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
791 {
792 DWORD ret;
793
794 TRACE("pStats %p\n", pStats);
795 ret = getICMPStats(pStats);
796 TRACE("returning %ld\n", ret);
797 return ret;
798 }
799
800
801 /******************************************************************
802 * GetIfEntry (IPHLPAPI.@)
803 *
804 *
805 * PARAMS
806 *
807 * pIfRow [In/Out]
808 *
809 * RETURNS
810 *
811 * DWORD
812 *
813 */
814 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
815 {
816 DWORD ret;
817 const char *name;
818
819 TRACE("pIfRow %p\n", pIfRow);
820 if (!pIfRow)
821 return ERROR_INVALID_PARAMETER;
822
823 name = getInterfaceNameByIndex(pIfRow->dwIndex);
824 if (name) {
825 ret = getInterfaceEntryByIndex(pIfRow->dwIndex, pIfRow);
826 if (ret == NO_ERROR)
827 ret = getInterfaceStatsByName(name, pIfRow);
828 consumeInterfaceName(name);
829 }
830 else
831 ret = ERROR_INVALID_DATA;
832 TRACE("returning %ld\n", ret);
833 return ret;
834 }
835
836
837 static int IfTableSorter(const void *a, const void *b)
838 {
839 int ret;
840
841 if (a && b)
842 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex;
843 else
844 ret = 0;
845 return ret;
846 }
847
848
849 /******************************************************************
850 * GetIfTable (IPHLPAPI.@)
851 *
852 *
853 * PARAMS
854 *
855 * pIfTable [In/Out]
856 * pdwSize [In/Out]
857 * bOrder [In]
858 *
859 * RETURNS
860 *
861 * DWORD
862 *
863 */
864 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
865 {
866 DWORD ret;
867
868 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize,
869 (DWORD)bOrder);
870 if (!pdwSize)
871 ret = ERROR_INVALID_PARAMETER;
872 else {
873 DWORD numInterfaces = getNumInterfaces();
874 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces);
875 ULONG size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW);
876
877 if (!pIfTable || *pdwSize < size) {
878 *pdwSize = size;
879 ret = ERROR_INSUFFICIENT_BUFFER;
880 }
881 else {
882 InterfaceIndexTable *table = getInterfaceIndexTable();
883
884 if (table) {
885 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) *
886 sizeof(MIB_IFROW);
887 if (*pdwSize < size) {
888 *pdwSize = size;
889 ret = ERROR_INSUFFICIENT_BUFFER;
890 }
891 else {
892 DWORD ndx;
893
894 pIfTable->dwNumEntries = 0;
895 for (ndx = 0; ndx < table->numIndexes; ndx++) {
896 pIfTable->table[ndx].dwIndex = table->indexes[ndx];
897 GetIfEntry(&pIfTable->table[ndx]);
898 pIfTable->dwNumEntries++;
899 }
900 if (bOrder)
901 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
902 IfTableSorter);
903 ret = NO_ERROR;
904 }
905 free(table);
906 }
907 else
908 ret = ERROR_OUTOFMEMORY;
909 }
910 }
911 TRACE("returning %ld\n", ret);
912 return ret;
913 }
914
915
916 /******************************************************************
917 * GetInterfaceInfo (IPHLPAPI.@)
918 *
919 *
920 * PARAMS
921 *
922 * pIfTable [In/Out]
923 * dwOutBufLen [In/Out]
924 *
925 * RETURNS
926 *
927 * DWORD
928 *
929 */
930 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
931 {
932 DWORD ret;
933
934 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen);
935 if (!dwOutBufLen)
936 ret = ERROR_INVALID_PARAMETER;
937 else {
938 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
939 DPRINT("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces);
940 ULONG size = sizeof(IP_INTERFACE_INFO) + (numNonLoopbackInterfaces) *
941 sizeof(IP_ADAPTER_INDEX_MAP);
942
943 if (!pIfTable || *dwOutBufLen < size) {
944 *dwOutBufLen = size;
945 ret = ERROR_INSUFFICIENT_BUFFER;
946 }
947 else {
948 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
949 DPRINT("table->numIndexes == 0x%x\n", table->numIndexes);
950
951 if (table) {
952 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes) *
953 sizeof(IP_ADAPTER_INDEX_MAP);
954 if (*dwOutBufLen < size) {
955 *dwOutBufLen = size;
956 ret = ERROR_INSUFFICIENT_BUFFER;
957 }
958 else {
959 DWORD ndx;
960
961 pIfTable->NumAdapters = 0;
962 for (ndx = 0; ndx < table->numIndexes; ndx++) {
963 const char *walker, *name;
964 WCHAR *assigner;
965
966 pIfTable->Adapter[ndx].Index = table->indexes[ndx];
967 name = getInterfaceNameByIndex(table->indexes[ndx]);
968 for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
969 walker && *walker &&
970 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
971 walker++, assigner++)
972 *assigner = *walker;
973 *assigner = 0;
974 consumeInterfaceName(name);
975 pIfTable->NumAdapters++;
976 }
977 ret = NO_ERROR;
978 }
979 free(table);
980 }
981 else
982 ret = ERROR_OUTOFMEMORY;
983 }
984 }
985 TRACE("returning %ld\n", ret);
986 return ret;
987 }
988
989
990 static int IpAddrTableSorter(const void *a, const void *b)
991 {
992 int ret;
993
994 if (a && b)
995 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr;
996 else
997 ret = 0;
998 return ret;
999 }
1000
1001
1002 /******************************************************************
1003 * GetIpAddrTable (IPHLPAPI.@)
1004 *
1005 *
1006 * PARAMS
1007 *
1008 * pIpAddrTable [In/Out]
1009 * pdwSize [In/Out]
1010 * bOrder [In]
1011 *
1012 * RETURNS
1013 *
1014 * DWORD
1015 *
1016 */
1017 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
1018 {
1019 DWORD ret;
1020
1021 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize,
1022 (DWORD)bOrder);
1023 if (!pdwSize)
1024 ret = ERROR_INVALID_PARAMETER;
1025 else {
1026 DWORD numInterfaces = getNumInterfaces();
1027 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) *
1028 sizeof(MIB_IPADDRROW);
1029
1030 if (!pIpAddrTable || *pdwSize < size) {
1031 *pdwSize = size;
1032 ret = ERROR_INSUFFICIENT_BUFFER;
1033 }
1034 else {
1035 InterfaceIndexTable *table = getInterfaceIndexTable();
1036
1037 if (table) {
1038 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) *
1039 sizeof(MIB_IPADDRROW);
1040 if (*pdwSize < size) {
1041 *pdwSize = size;
1042 ret = ERROR_INSUFFICIENT_BUFFER;
1043 }
1044 else {
1045 DWORD ndx, bcast;
1046
1047 pIpAddrTable->dwNumEntries = 0;
1048 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1049 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx];
1050 pIpAddrTable->table[ndx].dwAddr =
1051 getInterfaceIPAddrByIndex(table->indexes[ndx]);
1052 pIpAddrTable->table[ndx].dwMask =
1053 getInterfaceMaskByIndex(table->indexes[ndx]);
1054 /* the dwBCastAddr member isn't the broadcast address, it indicates
1055 * whether the interface uses the 1's broadcast address (1) or the
1056 * 0's broadcast address (0).
1057 */
1058 bcast = getInterfaceBCastAddrByIndex(table->indexes[ndx]);
1059 pIpAddrTable->table[ndx].dwBCastAddr =
1060 (bcast & pIpAddrTable->table[ndx].dwMask) ? 1 : 0;
1061 /* FIXME: hardcoded reasm size, not sure where to get it */
1062 pIpAddrTable->table[ndx].dwReasmSize = 65535;
1063 pIpAddrTable->table[ndx].unused1 = 0;
1064 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */
1065 pIpAddrTable->dwNumEntries++;
1066 }
1067 if (bOrder)
1068 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries,
1069 sizeof(MIB_IPADDRROW), IpAddrTableSorter);
1070 ret = NO_ERROR;
1071 }
1072 free(table);
1073 }
1074 else
1075 ret = ERROR_OUTOFMEMORY;
1076 }
1077 }
1078 TRACE("returning %ld\n", ret);
1079 return ret;
1080 }
1081
1082
1083 static int IpForwardTableSorter(const void *a, const void *b)
1084 {
1085 int ret;
1086
1087 if (a && b) {
1088 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b;
1089
1090 ret = rowA->dwForwardDest - rowB->dwForwardDest;
1091 if (ret == 0) {
1092 ret = rowA->dwForwardProto - rowB->dwForwardProto;
1093 if (ret == 0) {
1094 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy;
1095 if (ret == 0)
1096 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop;
1097 }
1098 }
1099 }
1100 else
1101 ret = 0;
1102 return ret;
1103 }
1104
1105
1106 /******************************************************************
1107 * GetIpForwardTable (IPHLPAPI.@)
1108 *
1109 *
1110 * PARAMS
1111 *
1112 * pIpForwardTable [In/Out]
1113 * pdwSize [In/Out]
1114 * bOrder [In]
1115 *
1116 * RETURNS
1117 *
1118 * DWORD
1119 *
1120 */
1121 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
1122 {
1123 DWORD ret;
1124
1125 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable,
1126 pdwSize, (DWORD)bOrder);
1127 if (!pdwSize)
1128 ret = ERROR_INVALID_PARAMETER;
1129 else {
1130 DWORD numRoutes = getNumRoutes();
1131 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) *
1132 sizeof(MIB_IPFORWARDROW);
1133
1134 if (!pIpForwardTable || *pdwSize < sizeNeeded) {
1135 *pdwSize = sizeNeeded;
1136 ret = ERROR_INSUFFICIENT_BUFFER;
1137 }
1138 else {
1139 RouteTable *table = getRouteTable();
1140 if (table) {
1141 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) *
1142 sizeof(MIB_IPFORWARDROW);
1143 if (*pdwSize < sizeNeeded) {
1144 *pdwSize = sizeNeeded;
1145 ret = ERROR_INSUFFICIENT_BUFFER;
1146 }
1147 else {
1148 DWORD ndx;
1149
1150 pIpForwardTable->dwNumEntries = table->numRoutes;
1151 for (ndx = 0; ndx < numRoutes; ndx++) {
1152 pIpForwardTable->table[ndx].dwForwardIfIndex =
1153 table->routes[ndx].ifIndex;
1154 pIpForwardTable->table[ndx].dwForwardDest =
1155 table->routes[ndx].dest;
1156 pIpForwardTable->table[ndx].dwForwardMask =
1157 table->routes[ndx].mask;
1158 pIpForwardTable->table[ndx].dwForwardPolicy = 0;
1159 pIpForwardTable->table[ndx].dwForwardNextHop =
1160 table->routes[ndx].gateway;
1161 /* FIXME: this type is appropriate for local interfaces; may not
1162 always be appropriate */
1163 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
1164 /* FIXME: other protos might be appropriate, e.g. the default route
1165 is typically set with MIB_IPPROTO_NETMGMT instead */
1166 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL;
1167 /* punt on age and AS */
1168 pIpForwardTable->table[ndx].dwForwardAge = 0;
1169 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0;
1170 pIpForwardTable->table[ndx].dwForwardMetric1 =
1171 table->routes[ndx].metric;
1172 /* rest of the metrics are 0.. */
1173 pIpForwardTable->table[ndx].dwForwardMetric2 = 0;
1174 pIpForwardTable->table[ndx].dwForwardMetric3 = 0;
1175 pIpForwardTable->table[ndx].dwForwardMetric4 = 0;
1176 pIpForwardTable->table[ndx].dwForwardMetric5 = 0;
1177 }
1178 if (bOrder)
1179 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
1180 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
1181 ret = NO_ERROR;
1182 }
1183 free(table);
1184 }
1185 else
1186 ret = ERROR_OUTOFMEMORY;
1187 }
1188 }
1189 TRACE("returning %ld\n", ret);
1190 return ret;
1191 }
1192
1193
1194 static int IpNetTableSorter(const void *a, const void *b)
1195 {
1196 int ret;
1197
1198 if (a && b)
1199 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr;
1200 else
1201 ret = 0;
1202 return ret;
1203 }
1204
1205
1206 /******************************************************************
1207 * GetIpNetTable (IPHLPAPI.@)
1208 *
1209 *
1210 * PARAMS
1211 *
1212 * pIpNetTable [In/Out]
1213 * pdwSize [In/Out]
1214 * bOrder [In]
1215 *
1216 * RETURNS
1217 *
1218 * DWORD
1219 *
1220 */
1221 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
1222 {
1223 DWORD ret;
1224
1225 TRACE("pIpNetTable %p, pdwSize %p, bOrder %ld\n", pIpNetTable, pdwSize,
1226 (DWORD)bOrder);
1227 if (!pdwSize)
1228 ret = ERROR_INVALID_PARAMETER;
1229 else {
1230 DWORD numEntries = getNumArpEntries();
1231 ULONG size = sizeof(MIB_IPNETTABLE) + (numEntries - 1) *
1232 sizeof(MIB_IPNETROW);
1233
1234 if (!pIpNetTable || *pdwSize < size) {
1235 *pdwSize = size;
1236 ret = ERROR_INSUFFICIENT_BUFFER;
1237 }
1238 else {
1239 PMIB_IPNETTABLE table = getArpTable();
1240
1241 if (table) {
1242 size = sizeof(MIB_IPNETTABLE) + (table->dwNumEntries - 1) *
1243 sizeof(MIB_IPNETROW);
1244 if (*pdwSize < size) {
1245 *pdwSize = size;
1246 ret = ERROR_INSUFFICIENT_BUFFER;
1247 }
1248 else {
1249 memcpy(pIpNetTable, table, size);
1250 if (bOrder)
1251 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries,
1252 sizeof(MIB_IPNETROW), IpNetTableSorter);
1253 ret = NO_ERROR;
1254 }
1255 free(table);
1256 }
1257 else
1258 ret = ERROR_OUTOFMEMORY;
1259 }
1260 }
1261 TRACE("returning %ld\n", ret);
1262 return ret;
1263 }
1264
1265
1266 /******************************************************************
1267 * GetIpStatistics (IPHLPAPI.@)
1268 *
1269 *
1270 * PARAMS
1271 *
1272 * pStats [In/Out]
1273 *
1274 * RETURNS
1275 *
1276 * DWORD
1277 *
1278 */
1279 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
1280 {
1281 return GetIpStatisticsEx(pStats, PF_INET);
1282 }
1283
1284 /******************************************************************
1285 * GetIpStatisticsEx (IPHLPAPI.@)
1286 *
1287 *
1288 * PARAMS
1289 *
1290 * pStats [In/Out]
1291 * dwFamily [In]
1292 *
1293 * RETURNS
1294 *
1295 * DWORD
1296 *
1297 */
1298 DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
1299 {
1300 DWORD ret;
1301
1302 TRACE("pStats %p\n", pStats);
1303 ret = getIPStats(pStats, dwFamily);
1304 TRACE("returning %ld\n", ret);
1305 return ret;
1306 }
1307
1308 /******************************************************************
1309 * GetNetworkParams (IPHLPAPI.@)
1310 *
1311 *
1312 * PARAMS
1313 *
1314 * pFixedInfo [In/Out]
1315 * pOutBufLen [In/Out]
1316 *
1317 * RETURNS
1318 *
1319 * DWORD
1320 *
1321 */
1322 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
1323 {
1324 DWORD ret, size;
1325 LONG regReturn;
1326 HKEY hKey;
1327 PIPHLP_RES_INFO resInfo;
1328
1329 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen);
1330 if (!pOutBufLen)
1331 return ERROR_INVALID_PARAMETER;
1332
1333 resInfo = getResInfo();
1334 if (!resInfo)
1335 return ERROR_OUTOFMEMORY;
1336
1337 size = sizeof(FIXED_INFO) + (resInfo->riCount > 0 ? (resInfo->riCount - 1) *
1338 sizeof(IP_ADDR_STRING) : 0);
1339 if (!pFixedInfo || *pOutBufLen < size) {
1340 *pOutBufLen = size;
1341 disposeResInfo( resInfo );
1342 return ERROR_BUFFER_OVERFLOW;
1343 }
1344
1345 memset(pFixedInfo, 0, size);
1346 size = sizeof(pFixedInfo->HostName);
1347 GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
1348 size = sizeof(pFixedInfo->DomainName);
1349 GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
1350
1351 TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName);
1352
1353 if (resInfo->riCount > 0) {
1354 PIP_ADDR_STRING ptr;
1355 int i;
1356
1357 for (i = 0, ptr = &pFixedInfo->DnsServerList; i < resInfo->riCount && ptr;
1358 i++, ptr = ptr->Next) {
1359 struct sockaddr_in *addr_v4 =
1360 (struct sockaddr_in *)&resInfo->riAddressList[i];
1361 toIPAddressString
1362 (addr_v4->sin_addr.s_addr,
1363 ptr->IpAddress.String);
1364 if (i == resInfo->riCount - 1)
1365 ptr->Next = NULL;
1366 else if (i == 0)
1367 ptr->Next = (PIP_ADDR_STRING)((LPBYTE)pFixedInfo + sizeof(FIXED_INFO));
1368 else
1369 ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDR_STRING));
1370 }
1371 }
1372 pFixedInfo->NodeType = HYBRID_NODETYPE;
1373 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1374 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey);
1375 if (regReturn != ERROR_SUCCESS)
1376 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1377 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ,
1378 &hKey);
1379 if (regReturn == ERROR_SUCCESS)
1380 {
1381 DWORD size = sizeof(pFixedInfo->ScopeId);
1382
1383 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, pFixedInfo->ScopeId, &size);
1384 RegCloseKey(hKey);
1385 }
1386
1387 disposeResInfo( resInfo );
1388 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
1389 I suppose could also check for a listener on port 53 to set EnableDns */
1390 ret = NO_ERROR;
1391 TRACE("returning %ld\n", ret);
1392
1393 return ret;
1394 }
1395
1396
1397 /******************************************************************
1398 * GetNumberOfInterfaces (IPHLPAPI.@)
1399 *
1400 *
1401 * PARAMS
1402 *
1403 * pdwNumIf [In/Out]
1404 *
1405 * RETURNS
1406 *
1407 * DWORD
1408 *
1409 */
1410 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
1411 {
1412 DWORD ret;
1413
1414 TRACE("pdwNumIf %p\n", pdwNumIf);
1415 if (!pdwNumIf)
1416 ret = ERROR_INVALID_PARAMETER;
1417 else {
1418 *pdwNumIf = getNumInterfaces();
1419 ret = NO_ERROR;
1420 }
1421 TRACE("returning %ld\n", ret);
1422 return ret;
1423 }
1424
1425
1426 /******************************************************************
1427 * GetPerAdapterInfo (IPHLPAPI.@)
1428 *
1429 *
1430 * PARAMS
1431 *
1432 * IfIndex [In]
1433 * pPerAdapterInfo [In/Out]
1434 * pOutBufLen [In/Out]
1435 *
1436 * RETURNS
1437 *
1438 * DWORD
1439 *
1440 */
1441 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
1442 {
1443 TRACE("IfIndex %ld, pPerAdapterInfo %p, pOutBufLen %p\n", IfIndex,
1444 pPerAdapterInfo, pOutBufLen);
1445 FIXME(":stub\n");
1446 /* marking Win2K+ functions not supported */
1447 return ERROR_NOT_SUPPORTED;
1448 }
1449
1450
1451 /******************************************************************
1452 * GetRTTAndHopCount (IPHLPAPI.@)
1453 *
1454 *
1455 * PARAMS
1456 *
1457 * DestIpAddress [In]
1458 * HopCount [In/Out]
1459 * MaxHops [In]
1460 * RTT [In/Out]
1461 *
1462 * RETURNS
1463 *
1464 * BOOL
1465 *
1466 */
1467 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
1468 {
1469 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
1470 DestIpAddress, HopCount, MaxHops, RTT);
1471 FIXME(":stub\n");
1472 return (BOOL) 0;
1473 }
1474
1475
1476 /******************************************************************
1477 * GetTcpStatisticsEx (IPHLPAPI.@)
1478 *
1479 *
1480 * PARAMS
1481 *
1482 * pStats [In/Out]
1483 * dwFamily [In]
1484 *
1485 * RETURNS
1486 *
1487 * DWORD
1488 *
1489 */
1490 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
1491 {
1492 DWORD ret;
1493
1494 TRACE("pStats %p\n", pStats);
1495 ret = getTCPStats(pStats, dwFamily);
1496 TRACE("returning %ld\n", ret);
1497 return ret;
1498 }
1499
1500 /******************************************************************
1501 * GetTcpStatistics (IPHLPAPI.@)
1502 *
1503 *
1504 * PARAMS
1505 *
1506 * pStats [In/Out]
1507 *
1508 * RETURNS
1509 *
1510 * DWORD
1511 *
1512 */
1513 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
1514 {
1515 return GetTcpStatisticsEx(pStats, PF_INET);
1516 }
1517
1518
1519 static int TcpTableSorter(const void *a, const void *b)
1520 {
1521 int ret;
1522
1523 if (a && b) {
1524 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
1525
1526 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1527 if (ret == 0) {
1528 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1529 if (ret == 0) {
1530 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
1531 if (ret == 0)
1532 ret = rowA->dwRemotePort - rowB->dwRemotePort;
1533 }
1534 }
1535 }
1536 else
1537 ret = 0;
1538 return ret;
1539 }
1540
1541
1542 /******************************************************************
1543 * GetTcpTable (IPHLPAPI.@)
1544 *
1545 *
1546 * PARAMS
1547 *
1548 * pTcpTable [In/Out]
1549 * pdwSize [In/Out]
1550 * bOrder [In]
1551 *
1552 * RETURNS
1553 *
1554 * DWORD
1555 *
1556 */
1557 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
1558 {
1559 DWORD ret;
1560
1561 TRACE("pTcpTable %p, pdwSize %p, bOrder %ld\n", pTcpTable, pdwSize,
1562 (DWORD)bOrder);
1563 if (!pdwSize)
1564 ret = ERROR_INVALID_PARAMETER;
1565 else {
1566 DWORD numEntries = getNumTcpEntries();
1567 ULONG size = sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW);
1568
1569 if (!pTcpTable || *pdwSize < size) {
1570 *pdwSize = size;
1571 ret = ERROR_INSUFFICIENT_BUFFER;
1572 }
1573 else {
1574 PMIB_TCPTABLE table = getTcpTable();
1575
1576 if (table) {
1577 size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) *
1578 sizeof(MIB_TCPROW);
1579 if (*pdwSize < size) {
1580 *pdwSize = size;
1581 ret = ERROR_INSUFFICIENT_BUFFER;
1582 }
1583 else {
1584 memcpy(pTcpTable, table, size);
1585 if (bOrder)
1586 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1587 sizeof(MIB_TCPROW), TcpTableSorter);
1588 ret = NO_ERROR;
1589 }
1590 free(table);
1591 }
1592 else
1593 ret = ERROR_OUTOFMEMORY;
1594 }
1595 }
1596 TRACE("returning %ld\n", ret);
1597 return ret;
1598 }
1599
1600
1601 /******************************************************************
1602 * GetUdpStatisticsEx (IPHLPAPI.@)
1603 *
1604 *
1605 * PARAMS
1606 *
1607 * pStats [In/Out]
1608 * dwFamily [In]
1609 *
1610 * RETURNS
1611 *
1612 * DWORD
1613 *
1614 */
1615 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
1616 {
1617 DWORD ret;
1618
1619 TRACE("pStats %p\n", pStats);
1620 ret = getUDPStats(pStats, dwFamily);
1621 TRACE("returning %ld\n", ret);
1622 return ret;
1623 }
1624
1625 /******************************************************************
1626 * GetUdpStatistics (IPHLPAPI.@)
1627 *
1628 *
1629 * PARAMS
1630 *
1631 * pStats [In/Out]
1632 *
1633 * RETURNS
1634 *
1635 * DWORD
1636 *
1637 */
1638 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1639 {
1640 return GetUdpStatisticsEx(pStats, PF_INET);
1641 }
1642
1643
1644 static int UdpTableSorter(const void *a, const void *b)
1645 {
1646 int ret;
1647
1648 if (a && b) {
1649 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1650
1651 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1652 if (ret == 0)
1653 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1654 }
1655 else
1656 ret = 0;
1657 return ret;
1658 }
1659
1660
1661 /******************************************************************
1662 * GetUdpTable (IPHLPAPI.@)
1663 *
1664 *
1665 * PARAMS
1666 *
1667 * pUdpTable [In/Out]
1668 * pdwSize [In/Out]
1669 * bOrder [In]
1670 *
1671 * RETURNS
1672 *
1673 * DWORD
1674 *
1675 */
1676 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1677 {
1678 DWORD ret;
1679
1680 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
1681 (DWORD)bOrder);
1682 if (!pdwSize)
1683 ret = ERROR_INVALID_PARAMETER;
1684 else {
1685 DWORD numEntries = getNumUdpEntries();
1686 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1687
1688 if (!pUdpTable || *pdwSize < size) {
1689 *pdwSize = size;
1690 ret = ERROR_INSUFFICIENT_BUFFER;
1691 }
1692 else {
1693 PMIB_UDPTABLE table = getUdpTable();
1694
1695 if (table) {
1696 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1697 sizeof(MIB_UDPROW);
1698 if (*pdwSize < size) {
1699 *pdwSize = size;
1700 ret = ERROR_INSUFFICIENT_BUFFER;
1701 }
1702 else {
1703 memcpy(pUdpTable, table, size);
1704 if (bOrder)
1705 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1706 sizeof(MIB_UDPROW), UdpTableSorter);
1707 ret = NO_ERROR;
1708 }
1709 free(table);
1710 }
1711 else
1712 ret = ERROR_OUTOFMEMORY;
1713 }
1714 }
1715 TRACE("returning %ld\n", ret);
1716 return ret;
1717 }
1718
1719
1720 /******************************************************************
1721 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1722 *
1723 *
1724 * PARAMS
1725 *
1726 * pIPIfInfo [In/Out]
1727 * dwOutBufLen [In/Out]
1728 *
1729 * RETURNS
1730 *
1731 * DWORD
1732 *
1733 */
1734 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1735 {
1736 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
1737 /* a unidirectional adapter?? not bloody likely! */
1738 return ERROR_NOT_SUPPORTED;
1739 }
1740
1741
1742 /******************************************************************
1743 * IpReleaseAddress (IPHLPAPI.@)
1744 *
1745 *
1746 * PARAMS
1747 *
1748 * AdapterInfo [In/Out]
1749 *
1750 * RETURNS
1751 *
1752 * DWORD
1753 *
1754 */
1755 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1756 {
1757 TRACE("AdapterInfo %p\n", AdapterInfo);
1758 /* not a stub, never going to support this (and I never mark an adapter as
1759 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1760 return ERROR_NOT_SUPPORTED;
1761 }
1762
1763
1764 /******************************************************************
1765 * IpRenewAddress (IPHLPAPI.@)
1766 *
1767 *
1768 * PARAMS
1769 *
1770 * AdapterInfo [In/Out]
1771 *
1772 * RETURNS
1773 *
1774 * DWORD
1775 *
1776 */
1777 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1778 {
1779 TRACE("AdapterInfo %p\n", AdapterInfo);
1780 /* not a stub, never going to support this (and I never mark an adapter as
1781 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1782 return ERROR_NOT_SUPPORTED;
1783 }
1784
1785
1786 /******************************************************************
1787 * NotifyAddrChange (IPHLPAPI.@)
1788 *
1789 *
1790 * PARAMS
1791 *
1792 * Handle [In/Out]
1793 * overlapped [In/Out]
1794 *
1795 * RETURNS
1796 *
1797 * DWORD
1798 *
1799 */
1800 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1801 {
1802 TRACE("Handle %p, overlapped %p\n", Handle, overlapped);
1803 FIXME(":stub\n");
1804 /* marking Win2K+ functions not supported */
1805 return ERROR_NOT_SUPPORTED;
1806 }
1807
1808
1809 /******************************************************************
1810 * NotifyRouteChange (IPHLPAPI.@)
1811 *
1812 *
1813 * PARAMS
1814 *
1815 * Handle [In/Out]
1816 * overlapped [In/Out]
1817 *
1818 * RETURNS
1819 *
1820 * DWORD
1821 *
1822 */
1823 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1824 {
1825 TRACE("Handle %p, overlapped %p\n", Handle, overlapped);
1826 FIXME(":stub\n");
1827 /* marking Win2K+ functions not supported */
1828 return ERROR_NOT_SUPPORTED;
1829 }
1830
1831
1832 /******************************************************************
1833 * SendARP (IPHLPAPI.@)
1834 *
1835 *
1836 * PARAMS
1837 *
1838 * DestIP [In]
1839 * SrcIP [In]
1840 * pMacAddr [In/Out]
1841 * PhyAddrLen [In/Out]
1842 *
1843 * RETURNS
1844 *
1845 * DWORD
1846 *
1847 */
1848 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
1849 {
1850 TRACE("DestIP 0x%08lx, SrcIP 0x%08lx, pMacAddr %p, PhyAddrLen %p\n", DestIP,
1851 SrcIP, pMacAddr, PhyAddrLen);
1852 FIXME(":stub\n");
1853 /* marking Win2K+ functions not supported */
1854 return ERROR_NOT_SUPPORTED;
1855 }
1856
1857
1858 /******************************************************************
1859 * SetIfEntry (IPHLPAPI.@)
1860 *
1861 *
1862 * PARAMS
1863 *
1864 * pIfRow [In/Out]
1865 *
1866 * RETURNS
1867 *
1868 * DWORD
1869 *
1870 */
1871 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
1872 {
1873 TRACE("pIfRow %p\n", pIfRow);
1874 /* this is supposed to set an administratively interface up or down.
1875 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
1876 this sort of down is indistinguishable from other sorts of down (e.g. no
1877 link). */
1878 FIXME(":stub\n");
1879 return ERROR_NOT_SUPPORTED;
1880 }
1881
1882
1883 /******************************************************************
1884 * SetIpForwardEntry (IPHLPAPI.@)
1885 *
1886 *
1887 * PARAMS
1888 *
1889 * pRoute [In/Out]
1890 *
1891 * RETURNS
1892 *
1893 * DWORD
1894 *
1895 */
1896 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
1897 {
1898 return setIpForwardEntry( pRoute );
1899 }
1900
1901
1902 /******************************************************************
1903 * SetIpNetEntry (IPHLPAPI.@)
1904 *
1905 *
1906 * PARAMS
1907 *
1908 * pArpEntry [In/Out]
1909 *
1910 * RETURNS
1911 *
1912 * DWORD
1913 *
1914 */
1915 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
1916 {
1917 TRACE("pArpEntry %p\n", pArpEntry);
1918 /* same as CreateIpNetEntry here, could use SIOCSARP, not sure I want to */
1919 FIXME(":stub\n");
1920 return (DWORD) 0;
1921 }
1922
1923
1924 /******************************************************************
1925 * SetIpStatistics (IPHLPAPI.@)
1926 *
1927 *
1928 * PARAMS
1929 *
1930 * pIpStats [In/Out]
1931 *
1932 * RETURNS
1933 *
1934 * DWORD
1935 *
1936 */
1937 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
1938 {
1939 TRACE("pIpStats %p\n", pIpStats);
1940 FIXME(":stub\n");
1941 return (DWORD) 0;
1942 }
1943
1944
1945 /******************************************************************
1946 * SetIpTTL (IPHLPAPI.@)
1947 *
1948 *
1949 * PARAMS
1950 *
1951 * nTTL [In]
1952 *
1953 * RETURNS
1954 *
1955 * DWORD
1956 *
1957 */
1958 DWORD WINAPI SetIpTTL(UINT nTTL)
1959 {
1960 TRACE("nTTL %d\n", nTTL);
1961 /* could echo nTTL > /proc/net/sys/net/ipv4/ip_default_ttl, not sure I
1962 want to. Could map EACCESS to ERROR_ACCESS_DENIED, I suppose */
1963 FIXME(":stub\n");
1964 return (DWORD) 0;
1965 }
1966
1967
1968 /******************************************************************
1969 * SetTcpEntry (IPHLPAPI.@)
1970 *
1971 *
1972 * PARAMS
1973 *
1974 * pTcpRow [In/Out]
1975 *
1976 * RETURNS
1977 *
1978 * DWORD
1979 *
1980 */
1981 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
1982 {
1983 TRACE("pTcpRow %p\n", pTcpRow);
1984 FIXME(":stub\n");
1985 return (DWORD) 0;
1986 }
1987
1988
1989 /******************************************************************
1990 * UnenableRouter (IPHLPAPI.@)
1991 *
1992 *
1993 * PARAMS
1994 *
1995 * pOverlapped [In/Out]
1996 * lpdwEnableCount [In/Out]
1997 *
1998 * RETURNS
1999 *
2000 * DWORD
2001 *
2002 */
2003 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
2004 {
2005 TRACE("pOverlapped %p, lpdwEnableCount %p\n", pOverlapped, lpdwEnableCount);
2006 FIXME(":stub\n");
2007 /* could echo "0" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
2008 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
2009 marking Win2K+ functions not supported */
2010 return ERROR_NOT_SUPPORTED;
2011 }
2012
2013 /*
2014 * @unimplemented
2015 */
2016 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
2017 {
2018 FIXME(":stub\n");
2019 return 0L;
2020 }
2021
2022
2023 /*
2024 * @unimplemented
2025 */
2026 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
2027 {
2028 FIXME(":stub\n");
2029 return 0L;
2030 }
2031
2032 /*
2033 * @unimplemented
2034 */
2035 DWORD WINAPI GetAdaptersAddresses(ULONG Family,DWORD Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
2036 {
2037 FIXME(":stub\n");
2038 return 0L;
2039 }
2040
2041 /*
2042 * @unimplemented
2043 */
2044 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
2045 {
2046 FIXME(":stub\n");
2047 return 0L;
2048 }
2049
2050 /*
2051 * @unimplemented
2052 */
2053 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
2054 {
2055 FIXME(":stub\n");
2056 return 0L;
2057 }
2058
2059 /*
2060 * @unimplemented
2061 */
2062 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
2063 {
2064 FIXME(":stub\n");
2065 return 0L;
2066 }
2067
2068 /*
2069 * @unimplemented
2070 */
2071 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
2072 {
2073 FIXME(":stub\n");
2074 return 0L;
2075 }
2076
2077