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