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