silence some warnings.
[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
617 for (ndx = 0; ndx < table->numIndexes; ndx++) {
618 PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
619 DWORD addrLen = sizeof(ptr->Address), type;
620 const char *ifname =
621 getInterfaceNameByIndex(table->indexes[ndx]);
622
623 /* on Win98 this is left empty, but whatever */
624
625 strncpy(ptr->AdapterName,ifname,sizeof(ptr->AdapterName));
626 consumeInterfaceName(ifname);
627 ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0';
628 getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen,
629 ptr->Address, &type);
630 /* MS defines address length and type as UINT in some places and
631 DWORD in others, **sigh**. Don't want to assume that PUINT and
632 PDWORD are equiv (64-bit?) */
633 ptr->AddressLength = addrLen;
634 ptr->Type = type;
635 ptr->Index = table->indexes[ndx];
636 toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]),
637 ptr->IpAddressList.IpAddress.String);
638 toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]),
639 ptr->IpAddressList.IpMask.String);
640 if (winsEnabled) {
641 ptr->HaveWins = TRUE;
642 memcpy(ptr->PrimaryWinsServer.IpAddress.String,
643 primaryWINS.String, sizeof(primaryWINS.String));
644 memcpy(ptr->SecondaryWinsServer.IpAddress.String,
645 secondaryWINS.String, sizeof(secondaryWINS.String));
646 }
647 if (ndx < table->numIndexes - 1)
648 ptr->Next = &pAdapterInfo[ndx + 1];
649 else
650 ptr->Next = NULL;
651 }
652 ret = NO_ERROR;
653 }
654 free(table);
655 }
656 else
657 ret = ERROR_OUTOFMEMORY;
658 }
659 }
660 else
661 ret = ERROR_NO_DATA;
662 }
663 TRACE("returning %ld\n", ret);
664 return ret;
665 }
666
667
668 /******************************************************************
669 * GetBestInterface (IPHLPAPI.@)
670 *
671 *
672 * PARAMS
673 *
674 * dwDestAddr [In]
675 * pdwBestIfIndex [In/Out]
676 *
677 * RETURNS
678 *
679 * DWORD
680 *
681 */
682 DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
683 {
684 DWORD ret;
685
686 TRACE("dwDestAddr 0x%08lx, pdwBestIfIndex %p\n", dwDestAddr, pdwBestIfIndex);
687 if (!pdwBestIfIndex)
688 ret = ERROR_INVALID_PARAMETER;
689 else {
690 MIB_IPFORWARDROW ipRow;
691
692 ret = GetBestRoute(dwDestAddr, 0, &ipRow);
693 if (ret == ERROR_SUCCESS)
694 *pdwBestIfIndex = ipRow.dwForwardIfIndex;
695 }
696 TRACE("returning %ld\n", ret);
697 return ret;
698 }
699
700
701 /******************************************************************
702 * GetBestRoute (IPHLPAPI.@)
703 *
704 *
705 * PARAMS
706 *
707 * dwDestAddr [In]
708 * dwSourceAddr [In]
709 * OUT [In]
710 *
711 * RETURNS
712 *
713 * DWORD
714 *
715 */
716 DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute)
717 {
718 PMIB_IPFORWARDTABLE table;
719 DWORD ret;
720
721 TRACE("dwDestAddr 0x%08lx, dwSourceAddr 0x%08lx, pBestRoute %p\n", dwDestAddr,
722 dwSourceAddr, pBestRoute);
723 if (!pBestRoute)
724 return ERROR_INVALID_PARAMETER;
725
726 AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
727 if (table) {
728 DWORD ndx, matchedBits, matchedNdx = 0;
729
730 for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
731 if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
732 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
733 DWORD numShifts, mask;
734
735 for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
736 mask && !(mask & 1); mask >>= 1, numShifts++)
737 ;
738 if (numShifts > matchedBits) {
739 matchedBits = numShifts;
740 matchedNdx = ndx;
741 }
742 }
743 }
744 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW));
745 HeapFree(GetProcessHeap(), 0, table);
746 ret = ERROR_SUCCESS;
747 }
748 else
749 ret = ERROR_OUTOFMEMORY;
750 TRACE("returning %ld\n", ret);
751 return ret;
752 }
753
754
755 /******************************************************************
756 * GetFriendlyIfIndex (IPHLPAPI.@)
757 *
758 *
759 * PARAMS
760 *
761 * IfIndex [In]
762 *
763 * RETURNS
764 *
765 * DWORD
766 *
767 */
768 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
769 {
770 /* windows doesn't validate these, either, just makes sure the top byte is
771 cleared. I assume my ifenum module never gives an index with the top
772 byte set. */
773 TRACE("returning %ld\n", IfIndex);
774 return IfIndex;
775 }
776
777
778 /******************************************************************
779 * GetIcmpStatistics (IPHLPAPI.@)
780 *
781 *
782 * PARAMS
783 *
784 * pStats [In/Out]
785 *
786 * RETURNS
787 *
788 * DWORD
789 *
790 */
791 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
792 {
793 DWORD ret;
794
795 TRACE("pStats %p\n", pStats);
796 ret = getICMPStats(pStats);
797 TRACE("returning %ld\n", ret);
798 return ret;
799 }
800
801
802 /******************************************************************
803 * GetIfEntry (IPHLPAPI.@)
804 *
805 *
806 * PARAMS
807 *
808 * pIfRow [In/Out]
809 *
810 * RETURNS
811 *
812 * DWORD
813 *
814 */
815 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
816 {
817 DWORD ret;
818 const char *name;
819
820 TRACE("pIfRow %p\n", pIfRow);
821 if (!pIfRow)
822 return ERROR_INVALID_PARAMETER;
823
824 name = getInterfaceNameByIndex(pIfRow->dwIndex);
825 if (name) {
826 ret = getInterfaceEntryByIndex(pIfRow->dwIndex, pIfRow);
827 if (ret == NO_ERROR)
828 ret = getInterfaceStatsByName(name, pIfRow);
829 consumeInterfaceName(name);
830 }
831 else
832 ret = ERROR_INVALID_DATA;
833 TRACE("returning %ld\n", ret);
834 return ret;
835 }
836
837
838 static int IfTableSorter(const void *a, const void *b)
839 {
840 int ret;
841
842 if (a && b)
843 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex;
844 else
845 ret = 0;
846 return ret;
847 }
848
849
850 /******************************************************************
851 * GetIfTable (IPHLPAPI.@)
852 *
853 *
854 * PARAMS
855 *
856 * pIfTable [In/Out]
857 * pdwSize [In/Out]
858 * bOrder [In]
859 *
860 * RETURNS
861 *
862 * DWORD
863 *
864 */
865 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
866 {
867 DWORD ret;
868
869 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize,
870 (DWORD)bOrder);
871 if (!pdwSize)
872 ret = ERROR_INVALID_PARAMETER;
873 else {
874 DWORD numInterfaces = getNumInterfaces();
875 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces);
876 ULONG size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW);
877
878 if (!pIfTable || *pdwSize < size) {
879 *pdwSize = size;
880 ret = ERROR_INSUFFICIENT_BUFFER;
881 }
882 else {
883 InterfaceIndexTable *table = getInterfaceIndexTable();
884
885 if (table) {
886 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) *
887 sizeof(MIB_IFROW);
888 if (*pdwSize < size) {
889 *pdwSize = size;
890 ret = ERROR_INSUFFICIENT_BUFFER;
891 }
892 else {
893 DWORD ndx;
894
895 pIfTable->dwNumEntries = 0;
896 for (ndx = 0; ndx < table->numIndexes; ndx++) {
897 pIfTable->table[ndx].dwIndex = table->indexes[ndx];
898 GetIfEntry(&pIfTable->table[ndx]);
899 pIfTable->dwNumEntries++;
900 }
901 if (bOrder)
902 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
903 IfTableSorter);
904 ret = NO_ERROR;
905 }
906 free(table);
907 }
908 else
909 ret = ERROR_OUTOFMEMORY;
910 }
911 }
912 TRACE("returning %ld\n", ret);
913 return ret;
914 }
915
916
917 /******************************************************************
918 * GetInterfaceInfo (IPHLPAPI.@)
919 *
920 *
921 * PARAMS
922 *
923 * pIfTable [In/Out]
924 * dwOutBufLen [In/Out]
925 *
926 * RETURNS
927 *
928 * DWORD
929 *
930 */
931 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
932 {
933 DWORD ret;
934
935 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen);
936 if (!dwOutBufLen)
937 ret = ERROR_INVALID_PARAMETER;
938 else {
939 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
940 DPRINT("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces);
941 ULONG size = sizeof(IP_INTERFACE_INFO) + (numNonLoopbackInterfaces) *
942 sizeof(IP_ADAPTER_INDEX_MAP);
943
944 if (!pIfTable || *dwOutBufLen < size) {
945 *dwOutBufLen = size;
946 ret = ERROR_INSUFFICIENT_BUFFER;
947 }
948 else {
949 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
950 DPRINT("table->numIndexes == 0x%x\n", table->numIndexes);
951
952 if (table) {
953 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes) *
954 sizeof(IP_ADAPTER_INDEX_MAP);
955 if (*dwOutBufLen < size) {
956 *dwOutBufLen = size;
957 ret = ERROR_INSUFFICIENT_BUFFER;
958 }
959 else {
960 DWORD ndx;
961
962 pIfTable->NumAdapters = 0;
963 for (ndx = 0; ndx < table->numIndexes; ndx++) {
964 const char *walker, *name;
965 WCHAR *assigner;
966
967 pIfTable->Adapter[ndx].Index = table->indexes[ndx];
968 name = getInterfaceNameByIndex(table->indexes[ndx]);
969 for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
970 walker && *walker &&
971 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
972 walker++, assigner++)
973 *assigner = *walker;
974 *assigner = 0;
975 consumeInterfaceName(name);
976 pIfTable->NumAdapters++;
977 }
978 ret = NO_ERROR;
979 }
980 free(table);
981 }
982 else
983 ret = ERROR_OUTOFMEMORY;
984 }
985 }
986 TRACE("returning %ld\n", ret);
987 return ret;
988 }
989
990
991 static int IpAddrTableSorter(const void *a, const void *b)
992 {
993 int ret;
994
995 if (a && b)
996 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr;
997 else
998 ret = 0;
999 return ret;
1000 }
1001
1002
1003 /******************************************************************
1004 * GetIpAddrTable (IPHLPAPI.@)
1005 *
1006 *
1007 * PARAMS
1008 *
1009 * pIpAddrTable [In/Out]
1010 * pdwSize [In/Out]
1011 * bOrder [In]
1012 *
1013 * RETURNS
1014 *
1015 * DWORD
1016 *
1017 */
1018 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
1019 {
1020 DWORD ret;
1021
1022 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize,
1023 (DWORD)bOrder);
1024 if (!pdwSize)
1025 ret = ERROR_INVALID_PARAMETER;
1026 else {
1027 DWORD numInterfaces = getNumInterfaces();
1028 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) *
1029 sizeof(MIB_IPADDRROW);
1030
1031 if (!pIpAddrTable || *pdwSize < size) {
1032 *pdwSize = size;
1033 ret = ERROR_INSUFFICIENT_BUFFER;
1034 }
1035 else {
1036 InterfaceIndexTable *table = getInterfaceIndexTable();
1037
1038 if (table) {
1039 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) *
1040 sizeof(MIB_IPADDRROW);
1041 if (*pdwSize < size) {
1042 *pdwSize = size;
1043 ret = ERROR_INSUFFICIENT_BUFFER;
1044 }
1045 else {
1046 DWORD ndx, bcast;
1047
1048 pIpAddrTable->dwNumEntries = 0;
1049 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1050 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx];
1051 pIpAddrTable->table[ndx].dwAddr =
1052 getInterfaceIPAddrByIndex(table->indexes[ndx]);
1053 pIpAddrTable->table[ndx].dwMask =
1054 getInterfaceMaskByIndex(table->indexes[ndx]);
1055 /* the dwBCastAddr member isn't the broadcast address, it indicates
1056 * whether the interface uses the 1's broadcast address (1) or the
1057 * 0's broadcast address (0).
1058 */
1059 bcast = getInterfaceBCastAddrByIndex(table->indexes[ndx]);
1060 pIpAddrTable->table[ndx].dwBCastAddr =
1061 (bcast & pIpAddrTable->table[ndx].dwMask) ? 1 : 0;
1062 /* FIXME: hardcoded reasm size, not sure where to get it */
1063 pIpAddrTable->table[ndx].dwReasmSize = 65535;
1064 pIpAddrTable->table[ndx].unused1 = 0;
1065 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */
1066 pIpAddrTable->dwNumEntries++;
1067 }
1068 if (bOrder)
1069 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries,
1070 sizeof(MIB_IPADDRROW), IpAddrTableSorter);
1071 ret = NO_ERROR;
1072 }
1073 free(table);
1074 }
1075 else
1076 ret = ERROR_OUTOFMEMORY;
1077 }
1078 }
1079 TRACE("returning %ld\n", ret);
1080 return ret;
1081 }
1082
1083
1084 static int IpForwardTableSorter(const void *a, const void *b)
1085 {
1086 int ret;
1087
1088 if (a && b) {
1089 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b;
1090
1091 ret = rowA->dwForwardDest - rowB->dwForwardDest;
1092 if (ret == 0) {
1093 ret = rowA->dwForwardProto - rowB->dwForwardProto;
1094 if (ret == 0) {
1095 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy;
1096 if (ret == 0)
1097 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop;
1098 }
1099 }
1100 }
1101 else
1102 ret = 0;
1103 return ret;
1104 }
1105
1106
1107 /******************************************************************
1108 * GetIpForwardTable (IPHLPAPI.@)
1109 *
1110 *
1111 * PARAMS
1112 *
1113 * pIpForwardTable [In/Out]
1114 * pdwSize [In/Out]
1115 * bOrder [In]
1116 *
1117 * RETURNS
1118 *
1119 * DWORD
1120 *
1121 */
1122 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
1123 {
1124 DWORD ret;
1125
1126 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable,
1127 pdwSize, (DWORD)bOrder);
1128 if (!pdwSize)
1129 ret = ERROR_INVALID_PARAMETER;
1130 else {
1131 DWORD numRoutes = getNumRoutes();
1132 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) *
1133 sizeof(MIB_IPFORWARDROW);
1134
1135 if (!pIpForwardTable || *pdwSize < sizeNeeded) {
1136 *pdwSize = sizeNeeded;
1137 ret = ERROR_INSUFFICIENT_BUFFER;
1138 }
1139 else {
1140 RouteTable *table = getRouteTable();
1141 if (table) {
1142 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) *
1143 sizeof(MIB_IPFORWARDROW);
1144 if (*pdwSize < sizeNeeded) {
1145 *pdwSize = sizeNeeded;
1146 ret = ERROR_INSUFFICIENT_BUFFER;
1147 }
1148 else {
1149 DWORD ndx;
1150
1151 pIpForwardTable->dwNumEntries = table->numRoutes;
1152 for (ndx = 0; ndx < numRoutes; ndx++) {
1153 pIpForwardTable->table[ndx].dwForwardIfIndex =
1154 table->routes[ndx].ifIndex;
1155 pIpForwardTable->table[ndx].dwForwardDest =
1156 table->routes[ndx].dest;
1157 pIpForwardTable->table[ndx].dwForwardMask =
1158 table->routes[ndx].mask;
1159 pIpForwardTable->table[ndx].dwForwardPolicy = 0;
1160 pIpForwardTable->table[ndx].dwForwardNextHop =
1161 table->routes[ndx].gateway;
1162 /* FIXME: this type is appropriate for local interfaces; may not
1163 always be appropriate */
1164 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
1165 /* FIXME: other protos might be appropriate, e.g. the default route
1166 is typically set with MIB_IPPROTO_NETMGMT instead */
1167 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL;
1168 /* punt on age and AS */
1169 pIpForwardTable->table[ndx].dwForwardAge = 0;
1170 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0;
1171 pIpForwardTable->table[ndx].dwForwardMetric1 =
1172 table->routes[ndx].metric;
1173 /* rest of the metrics are 0.. */
1174 pIpForwardTable->table[ndx].dwForwardMetric2 = 0;
1175 pIpForwardTable->table[ndx].dwForwardMetric3 = 0;
1176 pIpForwardTable->table[ndx].dwForwardMetric4 = 0;
1177 pIpForwardTable->table[ndx].dwForwardMetric5 = 0;
1178 }
1179 if (bOrder)
1180 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
1181 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
1182 ret = NO_ERROR;
1183 }
1184 free(table);
1185 }
1186 else
1187 ret = ERROR_OUTOFMEMORY;
1188 }
1189 }
1190 TRACE("returning %ld\n", ret);
1191 return ret;
1192 }
1193
1194
1195 static int IpNetTableSorter(const void *a, const void *b)
1196 {
1197 int ret;
1198
1199 if (a && b)
1200 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr;
1201 else
1202 ret = 0;
1203 return ret;
1204 }
1205
1206
1207 /******************************************************************
1208 * GetIpNetTable (IPHLPAPI.@)
1209 *
1210 *
1211 * PARAMS
1212 *
1213 * pIpNetTable [In/Out]
1214 * pdwSize [In/Out]
1215 * bOrder [In]
1216 *
1217 * RETURNS
1218 *
1219 * DWORD
1220 *
1221 */
1222 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
1223 {
1224 DWORD ret;
1225
1226 TRACE("pIpNetTable %p, pdwSize %p, bOrder %ld\n", pIpNetTable, pdwSize,
1227 (DWORD)bOrder);
1228 if (!pdwSize)
1229 ret = ERROR_INVALID_PARAMETER;
1230 else {
1231 DWORD numEntries = getNumArpEntries();
1232 ULONG size = sizeof(MIB_IPNETTABLE) + (numEntries - 1) *
1233 sizeof(MIB_IPNETROW);
1234
1235 if (!pIpNetTable || *pdwSize < size) {
1236 *pdwSize = size;
1237 ret = ERROR_INSUFFICIENT_BUFFER;
1238 }
1239 else {
1240 PMIB_IPNETTABLE table = getArpTable();
1241
1242 if (table) {
1243 size = sizeof(MIB_IPNETTABLE) + (table->dwNumEntries - 1) *
1244 sizeof(MIB_IPNETROW);
1245 if (*pdwSize < size) {
1246 *pdwSize = size;
1247 ret = ERROR_INSUFFICIENT_BUFFER;
1248 }
1249 else {
1250 memcpy(pIpNetTable, table, size);
1251 if (bOrder)
1252 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries,
1253 sizeof(MIB_IPNETROW), IpNetTableSorter);
1254 ret = NO_ERROR;
1255 }
1256 free(table);
1257 }
1258 else
1259 ret = ERROR_OUTOFMEMORY;
1260 }
1261 }
1262 TRACE("returning %ld\n", ret);
1263 return ret;
1264 }
1265
1266
1267 /******************************************************************
1268 * GetIpStatistics (IPHLPAPI.@)
1269 *
1270 *
1271 * PARAMS
1272 *
1273 * pStats [In/Out]
1274 *
1275 * RETURNS
1276 *
1277 * DWORD
1278 *
1279 */
1280 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
1281 {
1282 return GetIpStatisticsEx(pStats, PF_INET);
1283 }
1284
1285 /******************************************************************
1286 * GetIpStatisticsEx (IPHLPAPI.@)
1287 *
1288 *
1289 * PARAMS
1290 *
1291 * pStats [In/Out]
1292 * dwFamily [In]
1293 *
1294 * RETURNS
1295 *
1296 * DWORD
1297 *
1298 */
1299 DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
1300 {
1301 DWORD ret;
1302
1303 TRACE("pStats %p\n", pStats);
1304 ret = getIPStats(pStats, dwFamily);
1305 TRACE("returning %ld\n", ret);
1306 return ret;
1307 }
1308
1309 /******************************************************************
1310 * GetNetworkParams (IPHLPAPI.@)
1311 *
1312 *
1313 * PARAMS
1314 *
1315 * pFixedInfo [In/Out]
1316 * pOutBufLen [In/Out]
1317 *
1318 * RETURNS
1319 *
1320 * DWORD
1321 *
1322 */
1323 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
1324 {
1325 DWORD ret, size;
1326 LONG regReturn;
1327 HKEY hKey;
1328 PIPHLP_RES_INFO resInfo;
1329
1330 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen);
1331 if (!pOutBufLen)
1332 return ERROR_INVALID_PARAMETER;
1333
1334 resInfo = getResInfo();
1335 if (!resInfo)
1336 return ERROR_OUTOFMEMORY;
1337
1338 size = sizeof(FIXED_INFO) + (resInfo->riCount > 0 ? (resInfo->riCount - 1) *
1339 sizeof(IP_ADDR_STRING) : 0);
1340 if (!pFixedInfo || *pOutBufLen < size) {
1341 *pOutBufLen = size;
1342 disposeResInfo( resInfo );
1343 return ERROR_BUFFER_OVERFLOW;
1344 }
1345
1346 memset(pFixedInfo, 0, size);
1347 size = sizeof(pFixedInfo->HostName);
1348 GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
1349 size = sizeof(pFixedInfo->DomainName);
1350 GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
1351
1352 TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName);
1353
1354 if (resInfo->riCount > 0) {
1355 PIP_ADDR_STRING ptr;
1356 int i;
1357
1358 for (i = 0, ptr = &pFixedInfo->DnsServerList; i < resInfo->riCount && ptr;
1359 i++, ptr = ptr->Next) {
1360 struct sockaddr_in *addr_v4 =
1361 (struct sockaddr_in *)&resInfo->riAddressList[i];
1362 toIPAddressString
1363 (addr_v4->sin_addr.s_addr,
1364 ptr->IpAddress.String);
1365 if (i == resInfo->riCount - 1)
1366 ptr->Next = NULL;
1367 else if (i == 0)
1368 ptr->Next = (PIP_ADDR_STRING)((LPBYTE)pFixedInfo + sizeof(FIXED_INFO));
1369 else
1370 ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDR_STRING));
1371 }
1372 }
1373 pFixedInfo->NodeType = HYBRID_NODETYPE;
1374 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1375 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey);
1376 if (regReturn != ERROR_SUCCESS)
1377 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1378 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ,
1379 &hKey);
1380 if (regReturn == ERROR_SUCCESS)
1381 {
1382 DWORD size = sizeof(pFixedInfo->ScopeId);
1383
1384 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, pFixedInfo->ScopeId, &size);
1385 RegCloseKey(hKey);
1386 }
1387
1388 disposeResInfo( resInfo );
1389 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
1390 I suppose could also check for a listener on port 53 to set EnableDns */
1391 ret = NO_ERROR;
1392 TRACE("returning %ld\n", ret);
1393
1394 return ret;
1395 }
1396
1397
1398 /******************************************************************
1399 * GetNumberOfInterfaces (IPHLPAPI.@)
1400 *
1401 *
1402 * PARAMS
1403 *
1404 * pdwNumIf [In/Out]
1405 *
1406 * RETURNS
1407 *
1408 * DWORD
1409 *
1410 */
1411 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
1412 {
1413 DWORD ret;
1414
1415 TRACE("pdwNumIf %p\n", pdwNumIf);
1416 if (!pdwNumIf)
1417 ret = ERROR_INVALID_PARAMETER;
1418 else {
1419 *pdwNumIf = getNumInterfaces();
1420 ret = NO_ERROR;
1421 }
1422 TRACE("returning %ld\n", ret);
1423 return ret;
1424 }
1425
1426
1427 /******************************************************************
1428 * GetPerAdapterInfo (IPHLPAPI.@)
1429 *
1430 *
1431 * PARAMS
1432 *
1433 * IfIndex [In]
1434 * pPerAdapterInfo [In/Out]
1435 * pOutBufLen [In/Out]
1436 *
1437 * RETURNS
1438 *
1439 * DWORD
1440 *
1441 */
1442 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
1443 {
1444 TRACE("IfIndex %ld, pPerAdapterInfo %p, pOutBufLen %p\n", IfIndex,
1445 pPerAdapterInfo, pOutBufLen);
1446 FIXME(":stub\n");
1447 /* marking Win2K+ functions not supported */
1448 return ERROR_NOT_SUPPORTED;
1449 }
1450
1451
1452 /******************************************************************
1453 * GetRTTAndHopCount (IPHLPAPI.@)
1454 *
1455 *
1456 * PARAMS
1457 *
1458 * DestIpAddress [In]
1459 * HopCount [In/Out]
1460 * MaxHops [In]
1461 * RTT [In/Out]
1462 *
1463 * RETURNS
1464 *
1465 * BOOL
1466 *
1467 */
1468 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
1469 {
1470 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
1471 DestIpAddress, HopCount, MaxHops, RTT);
1472 FIXME(":stub\n");
1473 return (BOOL) 0;
1474 }
1475
1476
1477 /******************************************************************
1478 * GetTcpStatisticsEx (IPHLPAPI.@)
1479 *
1480 *
1481 * PARAMS
1482 *
1483 * pStats [In/Out]
1484 * dwFamily [In]
1485 *
1486 * RETURNS
1487 *
1488 * DWORD
1489 *
1490 */
1491 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
1492 {
1493 DWORD ret;
1494
1495 TRACE("pStats %p\n", pStats);
1496 ret = getTCPStats(pStats, dwFamily);
1497 TRACE("returning %ld\n", ret);
1498 return ret;
1499 }
1500
1501 /******************************************************************
1502 * GetTcpStatistics (IPHLPAPI.@)
1503 *
1504 *
1505 * PARAMS
1506 *
1507 * pStats [In/Out]
1508 *
1509 * RETURNS
1510 *
1511 * DWORD
1512 *
1513 */
1514 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
1515 {
1516 return GetTcpStatisticsEx(pStats, PF_INET);
1517 }
1518
1519
1520 static int TcpTableSorter(const void *a, const void *b)
1521 {
1522 int ret;
1523
1524 if (a && b) {
1525 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
1526
1527 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1528 if (ret == 0) {
1529 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1530 if (ret == 0) {
1531 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
1532 if (ret == 0)
1533 ret = rowA->dwRemotePort - rowB->dwRemotePort;
1534 }
1535 }
1536 }
1537 else
1538 ret = 0;
1539 return ret;
1540 }
1541
1542
1543 /******************************************************************
1544 * GetTcpTable (IPHLPAPI.@)
1545 *
1546 *
1547 * PARAMS
1548 *
1549 * pTcpTable [In/Out]
1550 * pdwSize [In/Out]
1551 * bOrder [In]
1552 *
1553 * RETURNS
1554 *
1555 * DWORD
1556 *
1557 */
1558 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
1559 {
1560 DWORD ret;
1561
1562 TRACE("pTcpTable %p, pdwSize %p, bOrder %ld\n", pTcpTable, pdwSize,
1563 (DWORD)bOrder);
1564 if (!pdwSize)
1565 ret = ERROR_INVALID_PARAMETER;
1566 else {
1567 DWORD numEntries = getNumTcpEntries();
1568 ULONG size = sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW);
1569
1570 if (!pTcpTable || *pdwSize < size) {
1571 *pdwSize = size;
1572 ret = ERROR_INSUFFICIENT_BUFFER;
1573 }
1574 else {
1575 PMIB_TCPTABLE table = getTcpTable();
1576
1577 if (table) {
1578 size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) *
1579 sizeof(MIB_TCPROW);
1580 if (*pdwSize < size) {
1581 *pdwSize = size;
1582 ret = ERROR_INSUFFICIENT_BUFFER;
1583 }
1584 else {
1585 memcpy(pTcpTable, table, size);
1586 if (bOrder)
1587 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1588 sizeof(MIB_TCPROW), TcpTableSorter);
1589 ret = NO_ERROR;
1590 }
1591 free(table);
1592 }
1593 else
1594 ret = ERROR_OUTOFMEMORY;
1595 }
1596 }
1597 TRACE("returning %ld\n", ret);
1598 return ret;
1599 }
1600
1601
1602 /******************************************************************
1603 * GetUdpStatisticsEx (IPHLPAPI.@)
1604 *
1605 *
1606 * PARAMS
1607 *
1608 * pStats [In/Out]
1609 * dwFamily [In]
1610 *
1611 * RETURNS
1612 *
1613 * DWORD
1614 *
1615 */
1616 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
1617 {
1618 DWORD ret;
1619
1620 TRACE("pStats %p\n", pStats);
1621 ret = getUDPStats(pStats, dwFamily);
1622 TRACE("returning %ld\n", ret);
1623 return ret;
1624 }
1625
1626 /******************************************************************
1627 * GetUdpStatistics (IPHLPAPI.@)
1628 *
1629 *
1630 * PARAMS
1631 *
1632 * pStats [In/Out]
1633 *
1634 * RETURNS
1635 *
1636 * DWORD
1637 *
1638 */
1639 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1640 {
1641 return GetUdpStatisticsEx(pStats, PF_INET);
1642 }
1643
1644
1645 static int UdpTableSorter(const void *a, const void *b)
1646 {
1647 int ret;
1648
1649 if (a && b) {
1650 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1651
1652 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1653 if (ret == 0)
1654 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1655 }
1656 else
1657 ret = 0;
1658 return ret;
1659 }
1660
1661
1662 /******************************************************************
1663 * GetUdpTable (IPHLPAPI.@)
1664 *
1665 *
1666 * PARAMS
1667 *
1668 * pUdpTable [In/Out]
1669 * pdwSize [In/Out]
1670 * bOrder [In]
1671 *
1672 * RETURNS
1673 *
1674 * DWORD
1675 *
1676 */
1677 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1678 {
1679 DWORD ret;
1680
1681 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
1682 (DWORD)bOrder);
1683 if (!pdwSize)
1684 ret = ERROR_INVALID_PARAMETER;
1685 else {
1686 DWORD numEntries = getNumUdpEntries();
1687 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1688
1689 if (!pUdpTable || *pdwSize < size) {
1690 *pdwSize = size;
1691 ret = ERROR_INSUFFICIENT_BUFFER;
1692 }
1693 else {
1694 PMIB_UDPTABLE table = getUdpTable();
1695
1696 if (table) {
1697 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1698 sizeof(MIB_UDPROW);
1699 if (*pdwSize < size) {
1700 *pdwSize = size;
1701 ret = ERROR_INSUFFICIENT_BUFFER;
1702 }
1703 else {
1704 memcpy(pUdpTable, table, size);
1705 if (bOrder)
1706 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1707 sizeof(MIB_UDPROW), UdpTableSorter);
1708 ret = NO_ERROR;
1709 }
1710 free(table);
1711 }
1712 else
1713 ret = ERROR_OUTOFMEMORY;
1714 }
1715 }
1716 TRACE("returning %ld\n", ret);
1717 return ret;
1718 }
1719
1720
1721 /******************************************************************
1722 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1723 *
1724 *
1725 * PARAMS
1726 *
1727 * pIPIfInfo [In/Out]
1728 * dwOutBufLen [In/Out]
1729 *
1730 * RETURNS
1731 *
1732 * DWORD
1733 *
1734 */
1735 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1736 {
1737 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
1738 /* a unidirectional adapter?? not bloody likely! */
1739 return ERROR_NOT_SUPPORTED;
1740 }
1741
1742
1743 /******************************************************************
1744 * IpReleaseAddress (IPHLPAPI.@)
1745 *
1746 *
1747 * PARAMS
1748 *
1749 * AdapterInfo [In/Out]
1750 *
1751 * RETURNS
1752 *
1753 * DWORD
1754 *
1755 */
1756 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1757 {
1758 TRACE("AdapterInfo %p\n", AdapterInfo);
1759 /* not a stub, never going to support this (and I never mark an adapter as
1760 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1761 return ERROR_NOT_SUPPORTED;
1762 }
1763
1764
1765 /******************************************************************
1766 * IpRenewAddress (IPHLPAPI.@)
1767 *
1768 *
1769 * PARAMS
1770 *
1771 * AdapterInfo [In/Out]
1772 *
1773 * RETURNS
1774 *
1775 * DWORD
1776 *
1777 */
1778 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1779 {
1780 TRACE("AdapterInfo %p\n", AdapterInfo);
1781 /* not a stub, never going to support this (and I never mark an adapter as
1782 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1783 return ERROR_NOT_SUPPORTED;
1784 }
1785
1786
1787 /******************************************************************
1788 * NotifyAddrChange (IPHLPAPI.@)
1789 *
1790 *
1791 * PARAMS
1792 *
1793 * Handle [In/Out]
1794 * overlapped [In/Out]
1795 *
1796 * RETURNS
1797 *
1798 * DWORD
1799 *
1800 */
1801 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1802 {
1803 TRACE("Handle %p, overlapped %p\n", Handle, overlapped);
1804 FIXME(":stub\n");
1805 /* marking Win2K+ functions not supported */
1806 return ERROR_NOT_SUPPORTED;
1807 }
1808
1809
1810 /******************************************************************
1811 * NotifyRouteChange (IPHLPAPI.@)
1812 *
1813 *
1814 * PARAMS
1815 *
1816 * Handle [In/Out]
1817 * overlapped [In/Out]
1818 *
1819 * RETURNS
1820 *
1821 * DWORD
1822 *
1823 */
1824 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1825 {
1826 TRACE("Handle %p, overlapped %p\n", Handle, overlapped);
1827 FIXME(":stub\n");
1828 /* marking Win2K+ functions not supported */
1829 return ERROR_NOT_SUPPORTED;
1830 }
1831
1832
1833 /******************************************************************
1834 * SendARP (IPHLPAPI.@)
1835 *
1836 *
1837 * PARAMS
1838 *
1839 * DestIP [In]
1840 * SrcIP [In]
1841 * pMacAddr [In/Out]
1842 * PhyAddrLen [In/Out]
1843 *
1844 * RETURNS
1845 *
1846 * DWORD
1847 *
1848 */
1849 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
1850 {
1851 TRACE("DestIP 0x%08lx, SrcIP 0x%08lx, pMacAddr %p, PhyAddrLen %p\n", DestIP,
1852 SrcIP, pMacAddr, PhyAddrLen);
1853 FIXME(":stub\n");
1854 /* marking Win2K+ functions not supported */
1855 return ERROR_NOT_SUPPORTED;
1856 }
1857
1858
1859 /******************************************************************
1860 * SetIfEntry (IPHLPAPI.@)
1861 *
1862 *
1863 * PARAMS
1864 *
1865 * pIfRow [In/Out]
1866 *
1867 * RETURNS
1868 *
1869 * DWORD
1870 *
1871 */
1872 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
1873 {
1874 TRACE("pIfRow %p\n", pIfRow);
1875 /* this is supposed to set an administratively interface up or down.
1876 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
1877 this sort of down is indistinguishable from other sorts of down (e.g. no
1878 link). */
1879 FIXME(":stub\n");
1880 return ERROR_NOT_SUPPORTED;
1881 }
1882
1883
1884 /******************************************************************
1885 * SetIpForwardEntry (IPHLPAPI.@)
1886 *
1887 *
1888 * PARAMS
1889 *
1890 * pRoute [In/Out]
1891 *
1892 * RETURNS
1893 *
1894 * DWORD
1895 *
1896 */
1897 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
1898 {
1899 return setIpForwardEntry( pRoute );
1900 }
1901
1902
1903 /******************************************************************
1904 * SetIpNetEntry (IPHLPAPI.@)
1905 *
1906 *
1907 * PARAMS
1908 *
1909 * pArpEntry [In/Out]
1910 *
1911 * RETURNS
1912 *
1913 * DWORD
1914 *
1915 */
1916 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
1917 {
1918 TRACE("pArpEntry %p\n", pArpEntry);
1919 /* same as CreateIpNetEntry here, could use SIOCSARP, not sure I want to */
1920 FIXME(":stub\n");
1921 return (DWORD) 0;
1922 }
1923
1924
1925 /******************************************************************
1926 * SetIpStatistics (IPHLPAPI.@)
1927 *
1928 *
1929 * PARAMS
1930 *
1931 * pIpStats [In/Out]
1932 *
1933 * RETURNS
1934 *
1935 * DWORD
1936 *
1937 */
1938 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
1939 {
1940 TRACE("pIpStats %p\n", pIpStats);
1941 FIXME(":stub\n");
1942 return (DWORD) 0;
1943 }
1944
1945
1946 /******************************************************************
1947 * SetIpTTL (IPHLPAPI.@)
1948 *
1949 *
1950 * PARAMS
1951 *
1952 * nTTL [In]
1953 *
1954 * RETURNS
1955 *
1956 * DWORD
1957 *
1958 */
1959 DWORD WINAPI SetIpTTL(UINT nTTL)
1960 {
1961 TRACE("nTTL %d\n", nTTL);
1962 /* could echo nTTL > /proc/net/sys/net/ipv4/ip_default_ttl, not sure I
1963 want to. Could map EACCESS to ERROR_ACCESS_DENIED, I suppose */
1964 FIXME(":stub\n");
1965 return (DWORD) 0;
1966 }
1967
1968
1969 /******************************************************************
1970 * SetTcpEntry (IPHLPAPI.@)
1971 *
1972 *
1973 * PARAMS
1974 *
1975 * pTcpRow [In/Out]
1976 *
1977 * RETURNS
1978 *
1979 * DWORD
1980 *
1981 */
1982 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
1983 {
1984 TRACE("pTcpRow %p\n", pTcpRow);
1985 FIXME(":stub\n");
1986 return (DWORD) 0;
1987 }
1988
1989
1990 /******************************************************************
1991 * UnenableRouter (IPHLPAPI.@)
1992 *
1993 *
1994 * PARAMS
1995 *
1996 * pOverlapped [In/Out]
1997 * lpdwEnableCount [In/Out]
1998 *
1999 * RETURNS
2000 *
2001 * DWORD
2002 *
2003 */
2004 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
2005 {
2006 TRACE("pOverlapped %p, lpdwEnableCount %p\n", pOverlapped, lpdwEnableCount);
2007 FIXME(":stub\n");
2008 /* could echo "0" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
2009 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
2010 marking Win2K+ functions not supported */
2011 return ERROR_NOT_SUPPORTED;
2012 }
2013
2014 /*
2015 * @unimplemented
2016 */
2017 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
2018 {
2019 FIXME(":stub\n");
2020 return 0L;
2021 }
2022
2023
2024 /*
2025 * @unimplemented
2026 */
2027 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
2028 {
2029 FIXME(":stub\n");
2030 return 0L;
2031 }
2032
2033 /*
2034 * @unimplemented
2035 */
2036 DWORD WINAPI GetAdaptersAddresses(ULONG Family,DWORD Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
2037 {
2038 FIXME(":stub\n");
2039 return 0L;
2040 }
2041
2042 /*
2043 * @unimplemented
2044 */
2045 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
2046 {
2047 FIXME(":stub\n");
2048 return 0L;
2049 }
2050
2051 /*
2052 * @unimplemented
2053 */
2054 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
2055 {
2056 FIXME(":stub\n");
2057 return 0L;
2058 }
2059
2060 /*
2061 * @unimplemented
2062 */
2063 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
2064 {
2065 FIXME(":stub\n");
2066 return 0L;
2067 }
2068
2069 /*
2070 * @unimplemented
2071 */
2072 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
2073 {
2074 FIXME(":stub\n");
2075 return 0L;
2076 }
2077
2078