[CMAKE]
[reactos.git] / dll / win32 / 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 #define DEBUG
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winreg.h"
44 #include "iphlpapi.h"
45 #include "dhcp.h"
46 #include "ifenum.h"
47 #include "ipstats.h"
48 #include "resinfo.h"
49 #include "route.h"
50 #include "wine/debug.h"
51 #include "dhcpcsdk.h"
52 #include "dhcpcapi.h"
53
54 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
55
56 typedef struct _NAME_SERVER_LIST_CONTEXT {
57 ULONG uSizeAvailable;
58 ULONG uSizeRequired;
59 PIP_PER_ADAPTER_INFO pData;
60 UINT NumServers;
61 IP_ADDR_STRING *pLastAddr;
62 } NAME_SERVER_LIST_CONTEXT, *PNAME_SERVER_LIST_CONTEXT;
63
64 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
65 {
66 switch (fdwReason) {
67 case DLL_PROCESS_ATTACH:
68 DisableThreadLibraryCalls( hinstDLL );
69 interfaceMapInit();
70 break;
71
72 case DLL_PROCESS_DETACH:
73 interfaceMapFree();
74 break;
75 }
76 return TRUE;
77 }
78
79 /******************************************************************
80 * AddIPAddress (IPHLPAPI.@)
81 *
82 *
83 * PARAMS
84 *
85 * Address [In]
86 * IpMask [In]
87 * IfIndex [In]
88 * NTEContext [In/Out]
89 * NTEInstance [In/Out]
90 *
91 * RETURNS
92 *
93 * DWORD
94 *
95 */
96 DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance)
97 {
98 return RtlNtStatusToDosError(addIPAddress(Address, Netmask, IfIndex, NteContext, NteInstance));
99 }
100
101 DWORD getInterfaceGatewayByIndex(DWORD index)
102 {
103 DWORD ndx, retVal = 0, numRoutes = getNumRoutes();
104 RouteTable *table = getRouteTable();
105 if (!table) return 0;
106
107 for (ndx = 0; ndx < numRoutes; ndx++)
108 {
109 if ((table->routes[ndx].ifIndex == (index)) && (table->routes[ndx].dest == 0))
110 retVal = table->routes[ndx].gateway;
111 }
112 HeapFree(GetProcessHeap(), 0, table);
113 return retVal;
114 }
115
116 /******************************************************************
117 * AllocateAndGetIfTableFromStack (IPHLPAPI.@)
118 *
119 *
120 * PARAMS
121 *
122 * ppIfTable [Out] -- pointer into which the MIB_IFTABLE is
123 * allocated and returned.
124 * bOrder [In] -- passed to GetIfTable to order the table
125 * heap [In] -- heap from which the table is allocated
126 * flags [In] -- flags to HeapAlloc
127 *
128 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
129 * GetIfTable returns otherwise
130 *
131 */
132 DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable,
133 BOOL bOrder, HANDLE heap, DWORD flags)
134 {
135 DWORD ret;
136
137 TRACE("ppIfTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n", ppIfTable,
138 (DWORD)bOrder, (DWORD)heap, flags);
139 if (!ppIfTable)
140 ret = ERROR_INVALID_PARAMETER;
141 else {
142 DWORD dwSize = 0;
143
144 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
145 if (ret == ERROR_INSUFFICIENT_BUFFER) {
146 *ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize);
147 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
148 }
149 }
150 TRACE("returning %ld\n", ret);
151 return ret;
152 }
153
154
155 /******************************************************************
156 * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@)
157 *
158 *
159 * PARAMS
160 *
161 * ppIpAddrTable [Out]
162 * bOrder [In] -- passed to GetIpAddrTable to order the table
163 * heap [In] -- heap from which the table is allocated
164 * flags [In] -- flags to HeapAlloc
165 *
166 * RETURNS
167 *
168 * DWORD
169 *
170 */
171 DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
172 BOOL bOrder, HANDLE heap, DWORD flags)
173 {
174 DWORD ret;
175
176 TRACE("ppIpAddrTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
177 ppIpAddrTable, (DWORD)bOrder, (DWORD)heap, flags);
178 if (!ppIpAddrTable)
179 ret = ERROR_INVALID_PARAMETER;
180 else {
181 DWORD dwSize = 0;
182
183 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
184 if (ret == ERROR_INSUFFICIENT_BUFFER) {
185 *ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize);
186 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
187 }
188 }
189 TRACE("returning %ld\n", ret);
190 return ret;
191 }
192
193
194 /******************************************************************
195 * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
196 *
197 *
198 * ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is
199 * allocated and returned.
200 * bOrder [In] -- passed to GetIfTable to order the table
201 * heap [In] -- heap from which the table is allocated
202 * flags [In] -- flags to HeapAlloc
203 *
204 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
205 * GetIpForwardTable returns otherwise
206 *
207 */
208 DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *
209 ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags)
210 {
211 DWORD ret;
212
213 TRACE("ppIpForwardTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
214 ppIpForwardTable, (DWORD)bOrder, (DWORD)heap, flags);
215 if (!ppIpForwardTable)
216 ret = ERROR_INVALID_PARAMETER;
217 else {
218 DWORD dwSize = 0;
219
220 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
221 if (ret == ERROR_INSUFFICIENT_BUFFER) {
222 *ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize);
223 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
224 }
225 }
226 TRACE("returning %ld\n", ret);
227 return ret;
228 }
229
230
231 /******************************************************************
232 * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@)
233 *
234 *
235 * PARAMS
236 *
237 * ppIpNetTable [Out]
238 * bOrder [In] -- passed to GetIpNetTable to order the table
239 * heap [In] -- heap from which the table is allocated
240 * flags [In] -- flags to HeapAlloc
241 *
242 * RETURNS
243 *
244 * DWORD
245 *
246 */
247 DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable,
248 BOOL bOrder, HANDLE heap, DWORD flags)
249 {
250 DWORD ret;
251
252 TRACE("ppIpNetTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
253 ppIpNetTable, (DWORD)bOrder, (DWORD)heap, flags);
254 if (!ppIpNetTable)
255 ret = ERROR_INVALID_PARAMETER;
256 else {
257 DWORD dwSize = 0;
258
259 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
260 if (ret == ERROR_INSUFFICIENT_BUFFER) {
261 *ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize);
262 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
263 }
264 }
265 TRACE("returning %ld\n", ret);
266 return ret;
267 }
268
269
270 /******************************************************************
271 * AllocateAndGetTcpTableFromStack (IPHLPAPI.@)
272 *
273 *
274 * PARAMS
275 *
276 * ppTcpTable [Out]
277 * bOrder [In] -- passed to GetTcpTable to order the table
278 * heap [In] -- heap from which the table is allocated
279 * flags [In] -- flags to HeapAlloc
280 *
281 * RETURNS
282 *
283 * DWORD
284 *
285 */
286 DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
287 BOOL bOrder, HANDLE heap, DWORD flags)
288 {
289 DWORD ret;
290
291 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
292 ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags);
293 if (!ppTcpTable)
294 ret = ERROR_INVALID_PARAMETER;
295 else {
296 DWORD dwSize = 0;
297
298 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
299 if (ret == ERROR_INSUFFICIENT_BUFFER) {
300 *ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize);
301 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
302 }
303 }
304 TRACE("returning %ld\n", ret);
305 return ret;
306 }
307
308
309 /******************************************************************
310 * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
311 *
312 *
313 * PARAMS
314 *
315 * ppUdpTable [Out]
316 * bOrder [In] -- passed to GetUdpTable to order the table
317 * heap [In] -- heap from which the table is allocated
318 * flags [In] -- flags to HeapAlloc
319 *
320 * RETURNS
321 *
322 * DWORD
323 *
324 */
325 DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
326 BOOL bOrder, HANDLE heap, DWORD flags)
327 {
328 DWORD ret;
329
330 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
331 ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags);
332 if (!ppUdpTable)
333 ret = ERROR_INVALID_PARAMETER;
334 else {
335 DWORD dwSize = 0;
336
337 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
338 if (ret == ERROR_INSUFFICIENT_BUFFER) {
339 *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize);
340 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
341 }
342 }
343 TRACE("returning %ld\n", ret);
344 return ret;
345 }
346
347
348 /******************************************************************
349 * CreateIpForwardEntry (IPHLPAPI.@)
350 *
351 *
352 * PARAMS
353 *
354 * pRoute [In/Out]
355 *
356 * RETURNS
357 *
358 * DWORD
359 *
360 */
361 DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
362 {
363 return createIpForwardEntry( pRoute );
364 }
365
366
367 /******************************************************************
368 * CreateIpNetEntry (IPHLPAPI.@)
369 *
370 *
371 * PARAMS
372 *
373 * pArpEntry [In/Out]
374 *
375 * RETURNS
376 *
377 * DWORD
378 *
379 */
380 DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
381 {
382 TRACE("pArpEntry %p\n", pArpEntry);
383 /* could use SIOCSARP on systems that support it, not sure I want to */
384 FIXME(":stub\n");
385 return (DWORD) 0;
386 }
387
388
389 /******************************************************************
390 * CreateProxyArpEntry (IPHLPAPI.@)
391 *
392 *
393 * PARAMS
394 *
395 * dwAddress [In]
396 * dwMask [In]
397 * dwIfIndex [In]
398 *
399 * RETURNS
400 *
401 * DWORD
402 *
403 */
404 DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
405 {
406 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
407 dwMask, dwIfIndex);
408 FIXME(":stub\n");
409 /* marking Win2K+ functions not supported */
410 return ERROR_NOT_SUPPORTED;
411 }
412
413
414 /******************************************************************
415 * DeleteIPAddress (IPHLPAPI.@)
416 *
417 *
418 * PARAMS
419 *
420 * NTEContext [In]
421 *
422 * RETURNS
423 *
424 * DWORD
425 *
426 */
427 DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
428 {
429 TRACE("NTEContext %ld\n", NTEContext);
430 return RtlNtStatusToDosError(deleteIpAddress(NTEContext));
431 }
432
433
434 /******************************************************************
435 * DeleteIpForwardEntry (IPHLPAPI.@)
436 *
437 *
438 * PARAMS
439 *
440 * pRoute [In/Out]
441 *
442 * RETURNS
443 *
444 * DWORD
445 *
446 */
447 DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
448 {
449 return deleteIpForwardEntry( pRoute );
450 }
451
452
453 /******************************************************************
454 * DeleteIpNetEntry (IPHLPAPI.@)
455 *
456 *
457 * PARAMS
458 *
459 * pArpEntry [In/Out]
460 *
461 * RETURNS
462 *
463 * DWORD
464 *
465 */
466 DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
467 {
468 TRACE("pArpEntry %p\n", pArpEntry);
469 /* could use SIOCDARP on systems that support it, not sure I want to */
470 FIXME(":stub\n");
471 return (DWORD) 0;
472 }
473
474
475 /******************************************************************
476 * DeleteProxyArpEntry (IPHLPAPI.@)
477 *
478 *
479 * PARAMS
480 *
481 * dwAddress [In]
482 * dwMask [In]
483 * dwIfIndex [In]
484 *
485 * RETURNS
486 *
487 * DWORD
488 *
489 */
490 DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
491 {
492 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
493 dwMask, dwIfIndex);
494 FIXME(":stub\n");
495 /* marking Win2K+ functions not supported */
496 return ERROR_NOT_SUPPORTED;
497 }
498
499 /******************************************************************
500 * EnableRouter (IPHLPAPI.@)
501 *
502 *
503 * PARAMS
504 *
505 * pHandle [In/Out]
506 * pOverlapped [In/Out]
507 *
508 * RETURNS
509 *
510 * DWORD
511 *
512 */
513 DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped)
514 {
515 TRACE("pHandle %p, pOverlapped %p\n", pHandle, pOverlapped);
516 FIXME(":stub\n");
517 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
518 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
519 marking Win2K+ functions not supported */
520 return ERROR_NOT_SUPPORTED;
521 }
522
523
524 /******************************************************************
525 * FlushIpNetTable (IPHLPAPI.@)
526 *
527 *
528 * PARAMS
529 *
530 * dwIfIndex [In]
531 *
532 * RETURNS
533 *
534 * DWORD
535 *
536 */
537 DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex)
538 {
539 TRACE("dwIfIndex 0x%08lx\n", dwIfIndex);
540 FIXME(":stub\n");
541 /* this flushes the arp cache of the given index
542 marking Win2K+ functions not supported */
543 return ERROR_NOT_SUPPORTED;
544 }
545
546
547 /******************************************************************
548 * GetAdapterIndex (IPHLPAPI.@)
549 *
550 *
551 * PARAMS
552 *
553 * AdapterName [In/Out]
554 * IfIndex [In/Out]
555 *
556 * RETURNS
557 *
558 * DWORD
559 *
560 */
561 DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
562 {
563 TRACE("AdapterName %p, IfIndex %p\n", AdapterName, IfIndex);
564 FIXME(":stub\n");
565 /* marking Win2K+ functions not supported */
566 return ERROR_NOT_SUPPORTED;
567 }
568
569
570 /******************************************************************
571 * GetAdaptersInfo (IPHLPAPI.@)
572 *
573 *
574 * PARAMS
575 *
576 * pAdapterInfo [In/Out]
577 * pOutBufLen [In/Out]
578 *
579 * RETURNS
580 *
581 * DWORD
582 *
583 */
584 DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
585 {
586 DWORD ret;
587 BOOL dhcpEnabled;
588 DWORD dhcpServer;
589
590 TRACE("pAdapterInfo %p, pOutBufLen %p\n", pAdapterInfo, pOutBufLen);
591 if (!pOutBufLen)
592 ret = ERROR_INVALID_PARAMETER;
593 else {
594 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
595
596 if (numNonLoopbackInterfaces > 0) {
597 /* this calculation assumes only one address in the IP_ADDR_STRING lists.
598 that's okay, because:
599 - we don't get multiple addresses per adapter anyway
600 - we don't know about per-adapter gateways
601 - DHCP and WINS servers can have max one entry per list */
602 ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces;
603
604 if (!pAdapterInfo || *pOutBufLen < size) {
605 *pOutBufLen = size;
606 ret = ERROR_BUFFER_OVERFLOW;
607 }
608 else {
609 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
610
611 if (table) {
612 size = sizeof(IP_ADAPTER_INFO) * table->numIndexes;
613 if (*pOutBufLen < size) {
614 *pOutBufLen = size;
615 ret = ERROR_INSUFFICIENT_BUFFER;
616 }
617 else {
618 DWORD ndx;
619 HKEY hKey;
620 BOOL winsEnabled = FALSE;
621 IP_ADDRESS_STRING primaryWINS, secondaryWINS;
622
623 memset(pAdapterInfo, 0, size);
624 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
625 "Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ,
626 &hKey) == ERROR_SUCCESS) {
627 DWORD size = sizeof(primaryWINS.String);
628 unsigned long addr;
629
630 RegQueryValueExA(hKey, "WinsServer", NULL, NULL,
631 (PBYTE)primaryWINS.String, &size);
632 addr = inet_addr(primaryWINS.String);
633 if (addr != INADDR_NONE && addr != INADDR_ANY)
634 winsEnabled = TRUE;
635 size = sizeof(secondaryWINS.String);
636 RegQueryValueExA(hKey, "BackupWinsServer", NULL, NULL,
637 (PBYTE)secondaryWINS.String, &size);
638 addr = inet_addr(secondaryWINS.String);
639 if (addr != INADDR_NONE && addr != INADDR_ANY)
640 winsEnabled = TRUE;
641 RegCloseKey(hKey);
642 }
643 TRACE("num of index is %lu\n", table->numIndexes);
644 for (ndx = 0; ndx < table->numIndexes; ndx++) {
645 PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
646 DWORD addrLen = sizeof(ptr->Address), type;
647 const char *ifname =
648 getInterfaceNameByIndex(table->indexes[ndx]);
649 if (!ifname) {
650 ret = ERROR_OUTOFMEMORY;
651 break;
652 }
653
654 /* on Win98 this is left empty, but whatever */
655 strncpy(ptr->AdapterName,ifname,sizeof(ptr->AdapterName));
656 consumeInterfaceName(ifname);
657 ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0';
658 getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen,
659 ptr->Address, &type);
660 /* MS defines address length and type as UINT in some places and
661 DWORD in others, **sigh**. Don't want to assume that PUINT and
662 PDWORD are equiv (64-bit?) */
663 ptr->AddressLength = addrLen;
664 ptr->Type = type;
665 ptr->Index = table->indexes[ndx];
666 toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]),
667 ptr->IpAddressList.IpAddress.String);
668 toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]),
669 ptr->IpAddressList.IpMask.String);
670 toIPAddressString(getInterfaceGatewayByIndex(table->indexes[ndx]),
671 ptr->GatewayList.IpAddress.String);
672 getDhcpInfoForAdapter(table->indexes[ndx], &dhcpEnabled,
673 &dhcpServer, &ptr->LeaseObtained,
674 &ptr->LeaseExpires);
675 ptr->DhcpEnabled = (DWORD) dhcpEnabled;
676 toIPAddressString(dhcpServer,
677 ptr->DhcpServer.IpAddress.String);
678 if (winsEnabled) {
679 ptr->HaveWins = TRUE;
680 memcpy(ptr->PrimaryWinsServer.IpAddress.String,
681 primaryWINS.String, sizeof(primaryWINS.String));
682 memcpy(ptr->SecondaryWinsServer.IpAddress.String,
683 secondaryWINS.String, sizeof(secondaryWINS.String));
684 }
685 if (ndx < table->numIndexes - 1)
686 ptr->Next = &pAdapterInfo[ndx + 1];
687 else
688 ptr->Next = NULL;
689 }
690 ret = NO_ERROR;
691 }
692 free(table);
693 }
694 else
695 ret = ERROR_OUTOFMEMORY;
696 }
697 }
698 else
699 ret = ERROR_NO_DATA;
700 }
701 TRACE("returning %ld\n", ret);
702 return ret;
703 }
704
705
706 /******************************************************************
707 * GetBestInterface (IPHLPAPI.@)
708 *
709 *
710 * PARAMS
711 *
712 * dwDestAddr [In]
713 * pdwBestIfIndex [In/Out]
714 *
715 * RETURNS
716 *
717 * DWORD
718 *
719 */
720 DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
721 {
722 DWORD ret;
723
724 TRACE("dwDestAddr 0x%08lx, pdwBestIfIndex %p\n", dwDestAddr, pdwBestIfIndex);
725 if (!pdwBestIfIndex)
726 ret = ERROR_INVALID_PARAMETER;
727 else {
728 MIB_IPFORWARDROW ipRow;
729
730 ret = GetBestRoute(dwDestAddr, 0, &ipRow);
731 if (ret == ERROR_SUCCESS)
732 *pdwBestIfIndex = ipRow.dwForwardIfIndex;
733 }
734 TRACE("returning %ld\n", ret);
735 return ret;
736 }
737
738
739 /******************************************************************
740 * GetBestRoute (IPHLPAPI.@)
741 *
742 *
743 * PARAMS
744 *
745 * dwDestAddr [In]
746 * dwSourceAddr [In]
747 * OUT [In]
748 *
749 * RETURNS
750 *
751 * DWORD
752 *
753 */
754 DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute)
755 {
756 PMIB_IPFORWARDTABLE table;
757 DWORD ret;
758
759 TRACE("dwDestAddr 0x%08lx, dwSourceAddr 0x%08lx, pBestRoute %p\n", dwDestAddr,
760 dwSourceAddr, pBestRoute);
761 if (!pBestRoute)
762 return ERROR_INVALID_PARAMETER;
763
764 AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
765 if (table) {
766 DWORD ndx, matchedBits, matchedNdx = 0;
767
768 for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
769 if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
770 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
771 DWORD numShifts, mask;
772
773 for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
774 mask && !(mask & 1); mask >>= 1, numShifts++)
775 ;
776 if (numShifts > matchedBits) {
777 matchedBits = numShifts;
778 matchedNdx = ndx;
779 }
780 }
781 }
782 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW));
783 HeapFree(GetProcessHeap(), 0, table);
784 ret = ERROR_SUCCESS;
785 }
786 else
787 ret = ERROR_OUTOFMEMORY;
788 TRACE("returning %ld\n", ret);
789 return ret;
790 }
791
792 /******************************************************************
793 * GetExtendedTcpTable (IPHLPAPI.@)
794 *
795 * Get the table of TCP endpoints available to the application.
796 *
797 * PARAMS
798 * pTcpTable [Out] table struct with the filtered TCP endpoints available to application
799 * pdwSize [In/Out] estimated size of the structure returned in pTcpTable, in bytes
800 * bOrder [In] whether to order the table
801 * ulAf [in] version of IP used by the TCP endpoints
802 * TableClass [in] type of the TCP table structure from TCP_TABLE_CLASS
803 * Reserved [in] reserved - this value must be zero
804 *
805 * RETURNS
806 * Success: NO_ERROR
807 * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER
808 *
809 * NOTES
810 */
811 DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved)
812 {
813 DWORD ret = NO_ERROR;
814 UNIMPLEMENTED;
815 return ret;
816 }
817
818
819 /******************************************************************
820 * GetFriendlyIfIndex (IPHLPAPI.@)
821 *
822 *
823 * PARAMS
824 *
825 * IfIndex [In]
826 *
827 * RETURNS
828 *
829 * DWORD
830 *
831 */
832 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
833 {
834 /* windows doesn't validate these, either, just makes sure the top byte is
835 cleared. I assume my ifenum module never gives an index with the top
836 byte set. */
837 TRACE("returning %ld\n", IfIndex);
838 return IfIndex;
839 }
840
841
842 /******************************************************************
843 * GetIcmpStatistics (IPHLPAPI.@)
844 *
845 *
846 * PARAMS
847 *
848 * pStats [In/Out]
849 *
850 * RETURNS
851 *
852 * DWORD
853 *
854 */
855 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
856 {
857 DWORD ret;
858
859 TRACE("pStats %p\n", pStats);
860 ret = getICMPStats(pStats);
861 TRACE("returning %ld\n", ret);
862 return ret;
863 }
864
865
866 /******************************************************************
867 * GetIfEntry (IPHLPAPI.@)
868 *
869 *
870 * PARAMS
871 *
872 * pIfRow [In/Out]
873 *
874 * RETURNS
875 *
876 * DWORD
877 *
878 */
879 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
880 {
881 DWORD ret;
882 const char *name;
883
884 TRACE("pIfRow %p\n", pIfRow);
885 if (!pIfRow)
886 return ERROR_INVALID_PARAMETER;
887
888 name = getInterfaceNameByIndex(pIfRow->dwIndex);
889 if (name) {
890 ret = getInterfaceEntryByIndex(pIfRow->dwIndex, pIfRow);
891 if (ret == NO_ERROR)
892 ret = getInterfaceStatsByName(name, pIfRow);
893 consumeInterfaceName(name);
894 }
895 else
896 ret = ERROR_INVALID_DATA;
897 TRACE("returning %ld\n", ret);
898 return ret;
899 }
900
901
902 static int IfTableSorter(const void *a, const void *b)
903 {
904 int ret;
905
906 if (a && b)
907 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex;
908 else
909 ret = 0;
910 return ret;
911 }
912
913
914 /******************************************************************
915 * GetIfTable (IPHLPAPI.@)
916 *
917 *
918 * PARAMS
919 *
920 * pIfTable [In/Out]
921 * pdwSize [In/Out]
922 * bOrder [In]
923 *
924 * RETURNS
925 *
926 * DWORD
927 *
928 */
929 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
930 {
931 DWORD ret;
932
933 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize,
934 (DWORD)bOrder);
935 if (!pdwSize)
936 ret = ERROR_INVALID_PARAMETER;
937 else {
938 DWORD numInterfaces = getNumInterfaces();
939 ULONG size;
940 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces);
941 size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW);
942
943 if (!pIfTable || *pdwSize < size) {
944 *pdwSize = size;
945 ret = ERROR_INSUFFICIENT_BUFFER;
946 }
947 else {
948 InterfaceIndexTable *table = getInterfaceIndexTable();
949
950 if (table) {
951 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) *
952 sizeof(MIB_IFROW);
953 if (*pdwSize < size) {
954 *pdwSize = size;
955 ret = ERROR_INSUFFICIENT_BUFFER;
956 }
957 else {
958 DWORD ndx;
959
960 pIfTable->dwNumEntries = 0;
961 for (ndx = 0; ndx < table->numIndexes; ndx++) {
962 pIfTable->table[ndx].dwIndex = table->indexes[ndx];
963 GetIfEntry(&pIfTable->table[ndx]);
964 pIfTable->dwNumEntries++;
965 }
966 if (bOrder)
967 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
968 IfTableSorter);
969 ret = NO_ERROR;
970 }
971 free(table);
972 }
973 else
974 ret = ERROR_OUTOFMEMORY;
975 }
976 }
977 TRACE("returning %ld\n", ret);
978 return ret;
979 }
980
981
982 /******************************************************************
983 * GetInterfaceInfo (IPHLPAPI.@)
984 *
985 *
986 * PARAMS
987 *
988 * pIfTable [In/Out]
989 * dwOutBufLen [In/Out]
990 *
991 * RETURNS
992 *
993 * DWORD
994 *
995 */
996 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
997 {
998 DWORD ret;
999
1000 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen);
1001 if (!dwOutBufLen)
1002 ret = ERROR_INVALID_PARAMETER;
1003 else {
1004 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
1005 ULONG size;
1006 TRACE("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces);
1007 size = sizeof(IP_INTERFACE_INFO) + (numNonLoopbackInterfaces) *
1008 sizeof(IP_ADAPTER_INDEX_MAP);
1009
1010 if (!pIfTable || *dwOutBufLen < size) {
1011 *dwOutBufLen = size;
1012 ret = ERROR_INSUFFICIENT_BUFFER;
1013 }
1014 else {
1015 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
1016
1017 if (table) {
1018 TRACE("table->numIndexes == 0x%x\n", table->numIndexes);
1019 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes) *
1020 sizeof(IP_ADAPTER_INDEX_MAP);
1021 if (*dwOutBufLen < size) {
1022 *dwOutBufLen = size;
1023 ret = ERROR_INSUFFICIENT_BUFFER;
1024 }
1025 else {
1026 DWORD ndx;
1027
1028 pIfTable->NumAdapters = 0;
1029 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1030 const char *walker, *name;
1031 WCHAR *assigner;
1032
1033 pIfTable->Adapter[ndx].Index = table->indexes[ndx];
1034 name = getInterfaceNameByIndex(table->indexes[ndx]);
1035 for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
1036 walker && *walker &&
1037 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
1038 walker++, assigner++)
1039 *assigner = *walker;
1040 *assigner = 0;
1041 consumeInterfaceName(name);
1042 pIfTable->NumAdapters++;
1043 }
1044 ret = NO_ERROR;
1045 }
1046 free(table);
1047 }
1048 else
1049 ret = ERROR_OUTOFMEMORY;
1050 }
1051 }
1052 TRACE("returning %ld\n", ret);
1053 return ret;
1054 }
1055
1056
1057 static int IpAddrTableSorter(const void *a, const void *b)
1058 {
1059 int ret;
1060
1061 if (a && b)
1062 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr;
1063 else
1064 ret = 0;
1065 return ret;
1066 }
1067
1068
1069 /******************************************************************
1070 * GetIpAddrTable (IPHLPAPI.@)
1071 *
1072 *
1073 * PARAMS
1074 *
1075 * pIpAddrTable [In/Out]
1076 * pdwSize [In/Out]
1077 * bOrder [In]
1078 *
1079 * RETURNS
1080 *
1081 * DWORD
1082 *
1083 */
1084 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
1085 {
1086 DWORD ret;
1087
1088 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize,
1089 (DWORD)bOrder);
1090 if (!pdwSize)
1091 ret = ERROR_INVALID_PARAMETER;
1092 else {
1093 DWORD numInterfaces = getNumInterfaces();
1094 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) *
1095 sizeof(MIB_IPADDRROW);
1096
1097 if (!pIpAddrTable || *pdwSize < size) {
1098 *pdwSize = size;
1099 ret = ERROR_INSUFFICIENT_BUFFER;
1100 }
1101 else {
1102 InterfaceIndexTable *table = getInterfaceIndexTable();
1103
1104 if (table) {
1105 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) *
1106 sizeof(MIB_IPADDRROW);
1107 if (*pdwSize < size) {
1108 *pdwSize = size;
1109 ret = ERROR_INSUFFICIENT_BUFFER;
1110 }
1111 else {
1112 DWORD ndx, bcast;
1113
1114 pIpAddrTable->dwNumEntries = 0;
1115 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1116 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx];
1117 pIpAddrTable->table[ndx].dwAddr =
1118 getInterfaceIPAddrByIndex(table->indexes[ndx]);
1119 pIpAddrTable->table[ndx].dwMask =
1120 getInterfaceMaskByIndex(table->indexes[ndx]);
1121 /* the dwBCastAddr member isn't the broadcast address, it indicates
1122 * whether the interface uses the 1's broadcast address (1) or the
1123 * 0's broadcast address (0).
1124 */
1125 bcast = getInterfaceBCastAddrByIndex(table->indexes[ndx]);
1126 pIpAddrTable->table[ndx].dwBCastAddr =
1127 (bcast & pIpAddrTable->table[ndx].dwMask) ? 1 : 0;
1128 /* FIXME: hardcoded reasm size, not sure where to get it */
1129 pIpAddrTable->table[ndx].dwReasmSize = 65535;
1130 pIpAddrTable->table[ndx].unused1 = 0;
1131 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */
1132 pIpAddrTable->dwNumEntries++;
1133 }
1134 if (bOrder)
1135 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries,
1136 sizeof(MIB_IPADDRROW), IpAddrTableSorter);
1137 ret = NO_ERROR;
1138 }
1139 free(table);
1140 }
1141 else
1142 ret = ERROR_OUTOFMEMORY;
1143 }
1144 }
1145 TRACE("returning %ld\n", ret);
1146 return ret;
1147 }
1148
1149
1150 static int IpForwardTableSorter(const void *a, const void *b)
1151 {
1152 int ret;
1153
1154 if (a && b) {
1155 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b;
1156
1157 ret = rowA->dwForwardDest - rowB->dwForwardDest;
1158 if (ret == 0) {
1159 ret = rowA->dwForwardProto - rowB->dwForwardProto;
1160 if (ret == 0) {
1161 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy;
1162 if (ret == 0)
1163 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop;
1164 }
1165 }
1166 }
1167 else
1168 ret = 0;
1169 return ret;
1170 }
1171
1172
1173 /******************************************************************
1174 * GetIpForwardTable (IPHLPAPI.@)
1175 *
1176 *
1177 * PARAMS
1178 *
1179 * pIpForwardTable [In/Out]
1180 * pdwSize [In/Out]
1181 * bOrder [In]
1182 *
1183 * RETURNS
1184 *
1185 * DWORD
1186 *
1187 */
1188 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
1189 {
1190 DWORD ret;
1191
1192 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable,
1193 pdwSize, (DWORD)bOrder);
1194 if (!pdwSize)
1195 ret = ERROR_INVALID_PARAMETER;
1196 else {
1197 DWORD numRoutes = getNumRoutes();
1198 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) *
1199 sizeof(MIB_IPFORWARDROW);
1200
1201 if (!pIpForwardTable || *pdwSize < sizeNeeded) {
1202 *pdwSize = sizeNeeded;
1203 ret = ERROR_INSUFFICIENT_BUFFER;
1204 }
1205 else {
1206 RouteTable *table = getRouteTable();
1207 if (table) {
1208 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) *
1209 sizeof(MIB_IPFORWARDROW);
1210 if (*pdwSize < sizeNeeded) {
1211 *pdwSize = sizeNeeded;
1212 ret = ERROR_INSUFFICIENT_BUFFER;
1213 }
1214 else {
1215 DWORD ndx;
1216
1217 pIpForwardTable->dwNumEntries = table->numRoutes;
1218 for (ndx = 0; ndx < numRoutes; ndx++) {
1219 pIpForwardTable->table[ndx].dwForwardIfIndex =
1220 table->routes[ndx].ifIndex + 1;
1221 pIpForwardTable->table[ndx].dwForwardDest =
1222 table->routes[ndx].dest;
1223 pIpForwardTable->table[ndx].dwForwardMask =
1224 table->routes[ndx].mask;
1225 pIpForwardTable->table[ndx].dwForwardPolicy = 0;
1226 pIpForwardTable->table[ndx].dwForwardNextHop =
1227 table->routes[ndx].gateway;
1228 /* FIXME: this type is appropriate for local interfaces; may not
1229 always be appropriate */
1230 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
1231 /* FIXME: other protos might be appropriate, e.g. the default route
1232 is typically set with MIB_IPPROTO_NETMGMT instead */
1233 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL;
1234 /* punt on age and AS */
1235 pIpForwardTable->table[ndx].dwForwardAge = 0;
1236 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0;
1237 pIpForwardTable->table[ndx].dwForwardMetric1 =
1238 table->routes[ndx].metric;
1239 /* rest of the metrics are 0.. */
1240 pIpForwardTable->table[ndx].dwForwardMetric2 = 0;
1241 pIpForwardTable->table[ndx].dwForwardMetric3 = 0;
1242 pIpForwardTable->table[ndx].dwForwardMetric4 = 0;
1243 pIpForwardTable->table[ndx].dwForwardMetric5 = 0;
1244 }
1245 if (bOrder)
1246 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
1247 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
1248 ret = NO_ERROR;
1249 }
1250 HeapFree(GetProcessHeap(), 0, table);
1251 }
1252 else
1253 ret = ERROR_OUTOFMEMORY;
1254 }
1255 }
1256 TRACE("returning %ld\n", ret);
1257 return ret;
1258 }
1259
1260
1261 static int IpNetTableSorter(const void *a, const void *b)
1262 {
1263 int ret;
1264
1265 if (a && b)
1266 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr;
1267 else
1268 ret = 0;
1269 return ret;
1270 }
1271
1272
1273 /******************************************************************
1274 * GetIpNetTable (IPHLPAPI.@)
1275 *
1276 *
1277 * PARAMS
1278 *
1279 * pIpNetTable [In/Out]
1280 * pdwSize [In/Out]
1281 * bOrder [In]
1282 *
1283 * RETURNS
1284 *
1285 * DWORD
1286 *
1287 */
1288 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
1289 {
1290 DWORD ret = NO_ERROR;
1291
1292 TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize,
1293 (DWORD)bOrder);
1294 if (!pdwSize)
1295 ret = ERROR_INVALID_PARAMETER;
1296 else {
1297 DWORD numEntries = getNumArpEntries();
1298 ULONG size = sizeof(MIB_IPNETTABLE);
1299
1300 if (numEntries > 1)
1301 size += (numEntries - 1) * sizeof(MIB_IPNETROW);
1302 if (!pIpNetTable || *pdwSize < size) {
1303 *pdwSize = size;
1304 ret = ERROR_INSUFFICIENT_BUFFER;
1305 }
1306 else {
1307 PMIB_IPNETTABLE table = getArpTable();
1308 if (table) {
1309 size = sizeof(MIB_IPNETTABLE);
1310 if (table->dwNumEntries > 1)
1311 size += (table->dwNumEntries - 1) * sizeof(MIB_IPNETROW);
1312 if (*pdwSize < size) {
1313 *pdwSize = size;
1314 ret = ERROR_INSUFFICIENT_BUFFER;
1315 }
1316 else {
1317 *pdwSize = size;
1318 memcpy(pIpNetTable, table, size);
1319 if (bOrder)
1320 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries,
1321 sizeof(MIB_IPNETROW), IpNetTableSorter);
1322 ret = NO_ERROR;
1323 }
1324 HeapFree(GetProcessHeap(), 0, table);
1325 }
1326 }
1327 }
1328 TRACE("returning %d\n", ret);
1329 return ret;
1330 }
1331
1332
1333 /******************************************************************
1334 * GetIpStatistics (IPHLPAPI.@)
1335 *
1336 *
1337 * PARAMS
1338 *
1339 * pStats [In/Out]
1340 *
1341 * RETURNS
1342 *
1343 * DWORD
1344 *
1345 */
1346 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
1347 {
1348 return GetIpStatisticsEx(pStats, PF_INET);
1349 }
1350
1351 /******************************************************************
1352 * GetIpStatisticsEx (IPHLPAPI.@)
1353 *
1354 *
1355 * PARAMS
1356 *
1357 * pStats [In/Out]
1358 * dwFamily [In]
1359 *
1360 * RETURNS
1361 *
1362 * DWORD
1363 *
1364 */
1365 DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
1366 {
1367 DWORD ret;
1368
1369 TRACE("pStats %p\n", pStats);
1370 ret = getIPStats(pStats, dwFamily);
1371 TRACE("returning %ld\n", ret);
1372 return ret;
1373 }
1374
1375 /******************************************************************
1376 * GetNetworkParams (IPHLPAPI.@)
1377 *
1378 *
1379 * PARAMS
1380 *
1381 * pFixedInfo [In/Out]
1382 * pOutBufLen [In/Out]
1383 *
1384 * RETURNS
1385 *
1386 * DWORD
1387 *
1388 */
1389 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
1390 {
1391 DWORD ret, size;
1392 LONG regReturn;
1393 HKEY hKey;
1394 PIPHLP_RES_INFO resInfo;
1395
1396 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen);
1397 if (!pOutBufLen)
1398 return ERROR_INVALID_PARAMETER;
1399
1400 resInfo = getResInfo();
1401 if (!resInfo)
1402 return ERROR_OUTOFMEMORY;
1403
1404 size = sizeof(FIXED_INFO) + (resInfo->riCount > 1 ? (resInfo->riCount-1) *
1405 sizeof(IP_ADDR_STRING) : 0);
1406 if (!pFixedInfo || *pOutBufLen < size) {
1407 *pOutBufLen = size;
1408 disposeResInfo( resInfo );
1409 return ERROR_BUFFER_OVERFLOW;
1410 }
1411
1412 memset(pFixedInfo, 0, size);
1413 size = sizeof(pFixedInfo->HostName);
1414 GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
1415 size = sizeof(pFixedInfo->DomainName);
1416 GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
1417
1418 TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName);
1419
1420 if (resInfo->riCount > 0)
1421 {
1422 CopyMemory(&pFixedInfo->DnsServerList, resInfo->DnsList, sizeof(IP_ADDR_STRING));
1423 if (resInfo->riCount > 1)
1424 {
1425 IP_ADDR_STRING *pSrc = resInfo->DnsList->Next;
1426 IP_ADDR_STRING *pTarget = (struct _IP_ADDR_STRING*)((char*)pFixedInfo + sizeof(FIXED_INFO));
1427
1428 pFixedInfo->DnsServerList.Next = pTarget;
1429
1430 do
1431 {
1432 CopyMemory(pTarget, pSrc, sizeof(IP_ADDR_STRING));
1433 resInfo->riCount--;
1434 if (resInfo->riCount > 1)
1435 {
1436 pTarget->Next = (IP_ADDR_STRING*)((char*)pTarget + sizeof(IP_ADDR_STRING));
1437 pTarget = pTarget->Next;
1438 pSrc = pSrc->Next;
1439 }
1440 else
1441 {
1442 pTarget->Next = NULL;
1443 break;
1444 }
1445 }
1446 while(TRUE);
1447 }
1448 else
1449 {
1450 pFixedInfo->DnsServerList.Next = NULL;
1451 }
1452 }
1453
1454 pFixedInfo->NodeType = HYBRID_NODETYPE;
1455 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1456 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey);
1457 if (regReturn != ERROR_SUCCESS)
1458 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1459 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ,
1460 &hKey);
1461 if (regReturn == ERROR_SUCCESS)
1462 {
1463 DWORD size = sizeof(pFixedInfo->ScopeId);
1464
1465 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (PBYTE)pFixedInfo->ScopeId, &size);
1466 RegCloseKey(hKey);
1467 }
1468
1469 disposeResInfo( resInfo );
1470 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
1471 I suppose could also check for a listener on port 53 to set EnableDns */
1472 ret = NO_ERROR;
1473 TRACE("returning %ld\n", ret);
1474
1475 return ret;
1476 }
1477
1478
1479 /******************************************************************
1480 * GetNumberOfInterfaces (IPHLPAPI.@)
1481 *
1482 *
1483 * PARAMS
1484 *
1485 * pdwNumIf [In/Out]
1486 *
1487 * RETURNS
1488 *
1489 * DWORD
1490 *
1491 */
1492 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
1493 {
1494 DWORD ret;
1495
1496 TRACE("pdwNumIf %p\n", pdwNumIf);
1497 if (!pdwNumIf)
1498 ret = ERROR_INVALID_PARAMETER;
1499 else {
1500 *pdwNumIf = getNumInterfaces();
1501 ret = NO_ERROR;
1502 }
1503 TRACE("returning %ld\n", ret);
1504 return ret;
1505 }
1506
1507
1508 /******************************************************************
1509 * GetOwnerModuleFromTcpEntry (IPHLPAPI.@)
1510 *
1511 * Get data about the module that issued the context bind for a specific IPv4 TCP endpoint in a MIB table row
1512 *
1513 * PARAMS
1514 * pTcpEntry [in] pointer to a MIB_TCPROW_OWNER_MODULE structure
1515 * Class [in] TCPIP_OWNER_MODULE_INFO_CLASS enumeration value
1516 * Buffer [out] pointer a buffer containing a TCPIP_OWNER_MODULE_BASIC_INFO structure with the owner module data.
1517 * pdwSize [in, out] estimated size of the structure returned in Buffer, in bytes
1518 *
1519 * RETURNS
1520 * Success: NO_ERROR
1521 * Failure: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY
1522 * ERROR_NOT_FOUND or ERROR_PARTIAL_COPY
1523 *
1524 * NOTES
1525 * The type of data returned in Buffer is indicated by the value of the Class parameter.
1526 */
1527 DWORD WINAPI GetOwnerModuleFromTcpEntry( PMIB_TCPROW_OWNER_MODULE pTcpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
1528 {
1529 DWORD ret = NO_ERROR;
1530 UNIMPLEMENTED;
1531 return ret;
1532 }
1533
1534
1535 /******************************************************************
1536 * GetPerAdapterInfo (IPHLPAPI.@)
1537 *
1538 *
1539 * PARAMS
1540 *
1541 * IfIndex [In]
1542 * pPerAdapterInfo [In/Out]
1543 * pOutBufLen [In/Out]
1544 *
1545 * RETURNS
1546 *
1547 * DWORD
1548 *
1549 */
1550 static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, PVOID Data)
1551 {
1552 IP_ADDR_STRING *pNext;
1553 PNAME_SERVER_LIST_CONTEXT Context = (PNAME_SERVER_LIST_CONTEXT)Data;
1554
1555 if (!Context->NumServers)
1556 {
1557 if (Context->uSizeAvailable >= Context->uSizeRequired)
1558 {
1559 WideCharToMultiByte(CP_ACP, 0, Server, -1, Context->pData->DnsServerList.IpAddress.String, 16, NULL, NULL);
1560 Context->pData->DnsServerList.IpAddress.String[15] = '\0';
1561 Context->pLastAddr = &Context->pData->DnsServerList;
1562 }
1563 }
1564 else
1565 {
1566 Context->uSizeRequired += sizeof(IP_ADDR_STRING);
1567 if (Context->uSizeAvailable >= Context->uSizeRequired)
1568 {
1569 pNext = (IP_ADDR_STRING*)(((char*)Context->pLastAddr) + sizeof(IP_ADDR_STRING));
1570 WideCharToMultiByte(CP_ACP, 0, Server, -1, pNext->IpAddress.String, 16, NULL, NULL);
1571 pNext->IpAddress.String[15] = '\0';
1572 Context->pLastAddr->Next = pNext;
1573 Context->pLastAddr = pNext;
1574 pNext->Next = NULL;
1575 }
1576 }
1577 Context->NumServers++;
1578 }
1579
1580 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
1581 {
1582 HKEY hkey;
1583 DWORD dwSize = 0;
1584 const char *ifName;
1585 NAME_SERVER_LIST_CONTEXT Context;
1586 WCHAR keyname[200] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
1587
1588 if (!pOutBufLen)
1589 return ERROR_INVALID_PARAMETER;
1590
1591 if (!pPerAdapterInfo || *pOutBufLen < sizeof(IP_PER_ADAPTER_INFO))
1592 {
1593 *pOutBufLen = sizeof(IP_PER_ADAPTER_INFO);
1594 return ERROR_BUFFER_OVERFLOW;
1595 }
1596
1597 ifName = getInterfaceNameByIndex(IfIndex);
1598 if (!ifName)
1599 return ERROR_INVALID_PARAMETER;
1600
1601 MultiByteToWideChar(CP_ACP, 0, ifName, -1, &keyname[62], sizeof(keyname)/sizeof(WCHAR) - 63);
1602 HeapFree(GetProcessHeap(), 0, (LPVOID)ifName);
1603
1604 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey) != ERROR_SUCCESS)
1605 {
1606 return ERROR_NOT_SUPPORTED;
1607 }
1608 Context.NumServers = 0;
1609 Context.uSizeAvailable = *pOutBufLen;
1610 Context.uSizeRequired = sizeof(IP_PER_ADAPTER_INFO);
1611 Context.pData = pPerAdapterInfo;
1612
1613 if (*pOutBufLen >= sizeof(IP_PER_ADAPTER_INFO))
1614 ZeroMemory(pPerAdapterInfo, sizeof(IP_PER_ADAPTER_INFO));
1615
1616 EnumNameServers(hkey, &keyname[62], &Context, CreateNameServerListEnumNamesFunc);
1617
1618 if (Context.uSizeRequired > Context.uSizeAvailable)
1619 {
1620 *pOutBufLen = Context.uSizeRequired;
1621 RegCloseKey(hkey);
1622 return ERROR_BUFFER_OVERFLOW;
1623 }
1624
1625 if(RegQueryValueExW(hkey, L"NameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
1626 {
1627 pPerAdapterInfo->AutoconfigActive = FALSE;
1628 }
1629 else
1630 {
1631 pPerAdapterInfo->AutoconfigActive = TRUE;
1632 }
1633
1634 RegCloseKey(hkey);
1635 return NOERROR;
1636 }
1637
1638
1639 /******************************************************************
1640 * GetRTTAndHopCount (IPHLPAPI.@)
1641 *
1642 *
1643 * PARAMS
1644 *
1645 * DestIpAddress [In]
1646 * HopCount [In/Out]
1647 * MaxHops [In]
1648 * RTT [In/Out]
1649 *
1650 * RETURNS
1651 *
1652 * BOOL
1653 *
1654 */
1655 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
1656 {
1657 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
1658 DestIpAddress, HopCount, MaxHops, RTT);
1659 FIXME(":stub\n");
1660 return (BOOL) 0;
1661 }
1662
1663
1664 /******************************************************************
1665 * GetTcpStatisticsEx (IPHLPAPI.@)
1666 *
1667 *
1668 * PARAMS
1669 *
1670 * pStats [In/Out]
1671 * dwFamily [In]
1672 *
1673 * RETURNS
1674 *
1675 * DWORD
1676 *
1677 */
1678 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
1679 {
1680 DWORD ret;
1681
1682 TRACE("pStats %p\n", pStats);
1683 ret = getTCPStats(pStats, dwFamily);
1684 TRACE("returning %ld\n", ret);
1685 return ret;
1686 }
1687
1688 /******************************************************************
1689 * GetTcpStatistics (IPHLPAPI.@)
1690 *
1691 *
1692 * PARAMS
1693 *
1694 * pStats [In/Out]
1695 *
1696 * RETURNS
1697 *
1698 * DWORD
1699 *
1700 */
1701 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
1702 {
1703 return GetTcpStatisticsEx(pStats, PF_INET);
1704 }
1705
1706
1707 static int TcpTableSorter(const void *a, const void *b)
1708 {
1709 int ret;
1710
1711 if (a && b) {
1712 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
1713
1714 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1715 if (ret == 0) {
1716 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1717 if (ret == 0) {
1718 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
1719 if (ret == 0)
1720 ret = rowA->dwRemotePort - rowB->dwRemotePort;
1721 }
1722 }
1723 }
1724 else
1725 ret = 0;
1726 return ret;
1727 }
1728
1729
1730 /******************************************************************
1731 * GetTcpTable (IPHLPAPI.@)
1732 *
1733 * Get the table of active TCP connections.
1734 *
1735 * PARAMS
1736 * pTcpTable [Out] buffer for TCP connections table
1737 * pdwSize [In/Out] length of output buffer
1738 * bOrder [In] whether to order the table
1739 *
1740 * RETURNS
1741 * Success: NO_ERROR
1742 * Failure: error code from winerror.h
1743 *
1744 * NOTES
1745 * If pdwSize is less than required, the function will return
1746 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to
1747 * the required byte size.
1748 * If bOrder is true, the returned table will be sorted, first by
1749 * local address and port number, then by remote address and port
1750 * number.
1751 */
1752 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
1753 {
1754 DWORD ret = ERROR_NO_DATA;
1755
1756 TRACE("pTcpTable %p, pdwSize %p, bOrder %d\n", pTcpTable, pdwSize,
1757 (DWORD)bOrder);
1758 if (!pdwSize)
1759 ret = ERROR_INVALID_PARAMETER;
1760 else {
1761 DWORD numEntries = getNumTcpEntries();
1762 DWORD size = sizeof(MIB_TCPTABLE);
1763
1764 if (numEntries > 1)
1765 size += (numEntries - 1) * sizeof(MIB_TCPROW);
1766 if (!pTcpTable || *pdwSize < size) {
1767 *pdwSize = size;
1768 ret = ERROR_INSUFFICIENT_BUFFER;
1769 }
1770 else {
1771 PMIB_TCPTABLE pOurTcpTable = getTcpTable();
1772 if (pOurTcpTable)
1773 {
1774 size = sizeof(MIB_TCPTABLE);
1775 if (pOurTcpTable->dwNumEntries > 1)
1776 size += (pOurTcpTable->dwNumEntries - 1) * sizeof(MIB_TCPROW);
1777
1778 if (*pdwSize < size)
1779 {
1780 *pdwSize = size;
1781
1782 ret = ERROR_INSUFFICIENT_BUFFER;
1783 }
1784 else
1785 {
1786 memcpy(pTcpTable, pOurTcpTable, size);
1787
1788 if (bOrder)
1789 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1790 sizeof(MIB_TCPROW), TcpTableSorter);
1791
1792 ret = NO_ERROR;
1793 }
1794
1795 free(pOurTcpTable);
1796 }
1797 }
1798 }
1799 TRACE("returning %d\n", ret);
1800 return ret;
1801 }
1802
1803
1804 /******************************************************************
1805 * GetUdpStatisticsEx (IPHLPAPI.@)
1806 *
1807 *
1808 * PARAMS
1809 *
1810 * pStats [In/Out]
1811 * dwFamily [In]
1812 *
1813 * RETURNS
1814 *
1815 * DWORD
1816 *
1817 */
1818 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
1819 {
1820 DWORD ret;
1821
1822 TRACE("pStats %p\n", pStats);
1823 ret = getUDPStats(pStats, dwFamily);
1824 TRACE("returning %ld\n", ret);
1825 return ret;
1826 }
1827
1828 /******************************************************************
1829 * GetUdpStatistics (IPHLPAPI.@)
1830 *
1831 *
1832 * PARAMS
1833 *
1834 * pStats [In/Out]
1835 *
1836 * RETURNS
1837 *
1838 * DWORD
1839 *
1840 */
1841 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1842 {
1843 return GetUdpStatisticsEx(pStats, PF_INET);
1844 }
1845
1846
1847 static int UdpTableSorter(const void *a, const void *b)
1848 {
1849 int ret;
1850
1851 if (a && b) {
1852 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1853
1854 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1855 if (ret == 0)
1856 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1857 }
1858 else
1859 ret = 0;
1860 return ret;
1861 }
1862
1863
1864 /******************************************************************
1865 * GetUdpTable (IPHLPAPI.@)
1866 *
1867 *
1868 * PARAMS
1869 *
1870 * pUdpTable [In/Out]
1871 * pdwSize [In/Out]
1872 * bOrder [In]
1873 *
1874 * RETURNS
1875 *
1876 * DWORD
1877 *
1878 */
1879 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1880 {
1881 DWORD ret;
1882
1883 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
1884 (DWORD)bOrder);
1885 if (!pdwSize)
1886 ret = ERROR_INVALID_PARAMETER;
1887 else {
1888 DWORD numEntries = getNumUdpEntries();
1889 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1890
1891 if (!pUdpTable || *pdwSize < size) {
1892 *pdwSize = size;
1893 ret = ERROR_INSUFFICIENT_BUFFER;
1894 }
1895 else {
1896 PMIB_UDPTABLE table = getUdpTable();
1897
1898 if (table) {
1899 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1900 sizeof(MIB_UDPROW);
1901 if (*pdwSize < size) {
1902 *pdwSize = size;
1903 ret = ERROR_INSUFFICIENT_BUFFER;
1904 }
1905 else {
1906 memcpy(pUdpTable, table, size);
1907 if (bOrder)
1908 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1909 sizeof(MIB_UDPROW), UdpTableSorter);
1910 ret = NO_ERROR;
1911 }
1912 free(table);
1913 }
1914 else
1915 ret = ERROR_OUTOFMEMORY;
1916 }
1917 }
1918 TRACE("returning %ld\n", ret);
1919 return ret;
1920 }
1921
1922
1923 /******************************************************************
1924 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1925 *
1926 * This is a Win98-only function to get information on "unidirectional"
1927 * adapters. Since this is pretty nonsensical in other contexts, it
1928 * never returns anything.
1929 *
1930 * PARAMS
1931 * pIPIfInfo [Out] buffer for adapter infos
1932 * dwOutBufLen [Out] length of the output buffer
1933 *
1934 * RETURNS
1935 * Success: NO_ERROR
1936 * Failure: error code from winerror.h
1937 *
1938 * FIXME
1939 * Stub, returns ERROR_NOT_SUPPORTED.
1940 */
1941 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1942 {
1943 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
1944 /* a unidirectional adapter?? not bloody likely! */
1945 return ERROR_NOT_SUPPORTED;
1946 }
1947
1948
1949 /******************************************************************
1950 * IpReleaseAddress (IPHLPAPI.@)
1951 *
1952 * Release an IP obtained through DHCP,
1953 *
1954 * PARAMS
1955 * AdapterInfo [In] adapter to release IP address
1956 *
1957 * RETURNS
1958 * Success: NO_ERROR
1959 * Failure: error code from winerror.h
1960 *
1961 */
1962 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1963 {
1964 DWORD Status, Version = 0;
1965
1966 if (!AdapterInfo || !AdapterInfo->Name)
1967 return ERROR_INVALID_PARAMETER;
1968
1969 /* Maybe we should do this in DllMain */
1970 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
1971 return ERROR_PROC_NOT_FOUND;
1972
1973 if (DhcpReleaseIpAddressLease(AdapterInfo->Index))
1974 Status = ERROR_SUCCESS;
1975 else
1976 Status = ERROR_PROC_NOT_FOUND;
1977
1978 DhcpCApiCleanup();
1979
1980 return Status;
1981 }
1982
1983
1984 /******************************************************************
1985 * IpRenewAddress (IPHLPAPI.@)
1986 *
1987 * Renew an IP obtained through DHCP.
1988 *
1989 * PARAMS
1990 * AdapterInfo [In] adapter to renew IP address
1991 *
1992 * RETURNS
1993 * Success: NO_ERROR
1994 * Failure: error code from winerror.h
1995 */
1996 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1997 {
1998 DWORD Status, Version = 0;
1999
2000 if (!AdapterInfo || !AdapterInfo->Name)
2001 return ERROR_INVALID_PARAMETER;
2002
2003 /* Maybe we should do this in DllMain */
2004 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
2005 return ERROR_PROC_NOT_FOUND;
2006
2007 if (DhcpRenewIpAddressLease(AdapterInfo->Index))
2008 Status = ERROR_SUCCESS;
2009 else
2010 Status = ERROR_PROC_NOT_FOUND;
2011
2012 DhcpCApiCleanup();
2013
2014 return Status;
2015 }
2016
2017
2018 /******************************************************************
2019 * NotifyAddrChange (IPHLPAPI.@)
2020 *
2021 * Notify caller whenever the ip-interface map is changed.
2022 *
2023 * PARAMS
2024 * Handle [Out] handle usable in asynchronous notification
2025 * overlapped [In] overlapped structure that notifies the caller
2026 *
2027 * RETURNS
2028 * Success: NO_ERROR
2029 * Failure: error code from winerror.h
2030 *
2031 * FIXME
2032 * Stub, returns ERROR_NOT_SUPPORTED.
2033 */
2034 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2035 {
2036 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2037 return ERROR_NOT_SUPPORTED;
2038 }
2039
2040
2041 /******************************************************************
2042 * NotifyRouteChange (IPHLPAPI.@)
2043 *
2044 * Notify caller whenever the ip routing table is changed.
2045 *
2046 * PARAMS
2047 * Handle [Out] handle usable in asynchronous notification
2048 * overlapped [In] overlapped structure that notifies the caller
2049 *
2050 * RETURNS
2051 * Success: NO_ERROR
2052 * Failure: error code from winerror.h
2053 *
2054 * FIXME
2055 * Stub, returns ERROR_NOT_SUPPORTED.
2056 */
2057 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2058 {
2059 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2060 return ERROR_NOT_SUPPORTED;
2061 }
2062
2063
2064 /******************************************************************
2065 * SendARP (IPHLPAPI.@)
2066 *
2067 * Send an ARP request.
2068 *
2069 * PARAMS
2070 * DestIP [In] attempt to obtain this IP
2071 * SrcIP [In] optional sender IP address
2072 * pMacAddr [Out] buffer for the mac address
2073 * PhyAddrLen [In/Out] length of the output buffer
2074 *
2075 * RETURNS
2076 * Success: NO_ERROR
2077 * Failure: error code from winerror.h
2078 *
2079 * FIXME
2080 * Stub, returns ERROR_NOT_SUPPORTED.
2081 */
2082 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
2083 {
2084 FIXME("(DestIP 0x%08x, SrcIP 0x%08x, pMacAddr %p, PhyAddrLen %p): stub\n",
2085 DestIP, SrcIP, pMacAddr, PhyAddrLen);
2086 return ERROR_NOT_SUPPORTED;
2087 }
2088
2089
2090 /******************************************************************
2091 * SetIfEntry (IPHLPAPI.@)
2092 *
2093 * Set the administrative status of an interface.
2094 *
2095 * PARAMS
2096 * pIfRow [In] dwAdminStatus member specifies the new status.
2097 *
2098 * RETURNS
2099 * Success: NO_ERROR
2100 * Failure: error code from winerror.h
2101 *
2102 * FIXME
2103 * Stub, returns ERROR_NOT_SUPPORTED.
2104 */
2105 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
2106 {
2107 FIXME("(pIfRow %p): stub\n", pIfRow);
2108 /* this is supposed to set an interface administratively up or down.
2109 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
2110 this sort of down is indistinguishable from other sorts of down (e.g. no
2111 link). */
2112 return ERROR_NOT_SUPPORTED;
2113 }
2114
2115
2116 /******************************************************************
2117 * SetIpForwardEntry (IPHLPAPI.@)
2118 *
2119 * Modify an existing route.
2120 *
2121 * PARAMS
2122 * pRoute [In] route with the new information
2123 *
2124 * RETURNS
2125 * Success: NO_ERROR
2126 * Failure: error code from winerror.h
2127 *
2128 */
2129 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
2130 {
2131 return setIpForwardEntry( pRoute );
2132 }
2133
2134
2135 /******************************************************************
2136 * SetIpNetEntry (IPHLPAPI.@)
2137 *
2138 * Modify an existing ARP entry.
2139 *
2140 * PARAMS
2141 * pArpEntry [In] ARP entry with the new information
2142 *
2143 * RETURNS
2144 * Success: NO_ERROR
2145 * Failure: error code from winerror.h
2146 */
2147 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
2148 {
2149 HANDLE tcpFile;
2150 NTSTATUS status;
2151 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req =
2152 TCP_REQUEST_SET_INFORMATION_INIT;
2153 TDIEntityID id;
2154 DWORD returnSize;
2155 PMIB_IPNETROW arpBuff;
2156
2157 if (!pArpEntry)
2158 return ERROR_INVALID_PARAMETER;
2159
2160 if (!NT_SUCCESS(openTcpFile( &tcpFile )))
2161 return ERROR_NOT_SUPPORTED;
2162
2163 if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id )))
2164 {
2165 closeTcpFile(tcpFile);
2166 return ERROR_INVALID_PARAMETER;
2167 }
2168
2169 req.Req.ID.toi_class = INFO_CLASS_PROTOCOL;
2170 req.Req.ID.toi_type = INFO_TYPE_PROVIDER;
2171 req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID;
2172 req.Req.ID.toi_entity.tei_instance = id.tei_instance;
2173 req.Req.ID.toi_entity.tei_entity = AT_ENTITY;
2174 req.Req.BufferSize = sizeof(MIB_IPNETROW);
2175 arpBuff = (PMIB_IPNETROW)&req.Req.Buffer[0];
2176
2177 RtlCopyMemory(arpBuff, pArpEntry, sizeof(MIB_IPNETROW));
2178
2179 status = DeviceIoControl( tcpFile,
2180 IOCTL_TCP_SET_INFORMATION_EX,
2181 &req,
2182 sizeof(req),
2183 NULL,
2184 0,
2185 &returnSize,
2186 NULL );
2187
2188 closeTcpFile(tcpFile);
2189
2190 if (status)
2191 return NO_ERROR;
2192 else
2193 return ERROR_INVALID_PARAMETER;
2194 }
2195
2196
2197 /******************************************************************
2198 * SetIpStatistics (IPHLPAPI.@)
2199 *
2200 * Toggle IP forwarding and det the default TTL value.
2201 *
2202 * PARAMS
2203 * pIpStats [In] IP statistics with the new information
2204 *
2205 * RETURNS
2206 * Success: NO_ERROR
2207 * Failure: error code from winerror.h
2208 *
2209 * FIXME
2210 * Stub, returns NO_ERROR.
2211 */
2212 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
2213 {
2214 FIXME("(pIpStats %p): stub\n", pIpStats);
2215 return 0;
2216 }
2217
2218
2219 /******************************************************************
2220 * SetIpTTL (IPHLPAPI.@)
2221 *
2222 * Set the default TTL value.
2223 *
2224 * PARAMS
2225 * nTTL [In] new TTL value
2226 *
2227 * RETURNS
2228 * Success: NO_ERROR
2229 * Failure: error code from winerror.h
2230 *
2231 * FIXME
2232 * Stub, returns NO_ERROR.
2233 */
2234 DWORD WINAPI SetIpTTL(UINT nTTL)
2235 {
2236 FIXME("(nTTL %d): stub\n", nTTL);
2237 return 0;
2238 }
2239
2240
2241 /******************************************************************
2242 * SetTcpEntry (IPHLPAPI.@)
2243 *
2244 * Set the state of a TCP connection.
2245 *
2246 * PARAMS
2247 * pTcpRow [In] specifies connection with new state
2248 *
2249 * RETURNS
2250 * Success: NO_ERROR
2251 * Failure: error code from winerror.h
2252 *
2253 * FIXME
2254 * Stub, returns NO_ERROR.
2255 */
2256 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
2257 {
2258 FIXME("(pTcpRow %p): stub\n", pTcpRow);
2259 return 0;
2260 }
2261
2262
2263 /******************************************************************
2264 * UnenableRouter (IPHLPAPI.@)
2265 *
2266 * Decrement the IP-forwarding reference count. Turn off IP-forwarding
2267 * if it reaches zero.
2268 *
2269 * PARAMS
2270 * pOverlapped [In/Out] should be the same as in EnableRouter()
2271 * lpdwEnableCount [Out] optional, receives reference count
2272 *
2273 * RETURNS
2274 * Success: NO_ERROR
2275 * Failure: error code from winerror.h
2276 *
2277 * FIXME
2278 * Stub, returns ERROR_NOT_SUPPORTED.
2279 */
2280 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
2281 {
2282 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped,
2283 lpdwEnableCount);
2284 return ERROR_NOT_SUPPORTED;
2285 }
2286
2287 /*
2288 * @unimplemented
2289 */
2290 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
2291 {
2292 FIXME(":stub\n");
2293 return 0L;
2294 }
2295
2296
2297 /*
2298 * @unimplemented
2299 */
2300 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
2301 {
2302 FIXME(":stub\n");
2303 return 0L;
2304 }
2305
2306 /*
2307 * @implemented
2308 */
2309 DWORD WINAPI GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
2310 {
2311 #if 0
2312 InterfaceIndexTable *indexTable;
2313 IFInfo ifInfo;
2314 int i;
2315 ULONG ret, requiredSize = 0;
2316 PIP_ADAPTER_ADDRESSES currentAddress;
2317 PUCHAR currentLocation;
2318 HANDLE tcpFile;
2319
2320 if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
2321 if (Reserved) return ERROR_INVALID_PARAMETER;
2322
2323 indexTable = getNonLoopbackInterfaceIndexTable(); //I think we want non-loopback here
2324 if (!indexTable)
2325 return ERROR_NOT_ENOUGH_MEMORY;
2326
2327 ret = openTcpFile(&tcpFile);
2328 if (!NT_SUCCESS(ret))
2329 return ERROR_NO_DATA;
2330
2331 for (i = indexTable->numIndexes; i >= 0; i--)
2332 {
2333 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
2334 NULL,
2335 indexTable->indexes[i],
2336 &ifInfo)))
2337 {
2338 /* The whole struct */
2339 requiredSize += sizeof(IP_ADAPTER_ADDRESSES);
2340
2341 /* Friendly name */
2342 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
2343 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1; //FIXME
2344
2345 /* Adapter name */
2346 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
2347
2348 /* Unicast address */
2349 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
2350 requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
2351
2352 /* FIXME: Implement multicast, anycast, and dns server stuff */
2353
2354 /* FIXME: Implement dns suffix and description */
2355 requiredSize += 2 * sizeof(WCHAR);
2356
2357 /* We're only going to implement what's required for XP SP0 */
2358 }
2359 }
2360
2361 if (*pOutBufLen < requiredSize)
2362 {
2363 *pOutBufLen = requiredSize;
2364 closeTcpFile(tcpFile);
2365 free(indexTable);
2366 return ERROR_BUFFER_OVERFLOW;
2367 }
2368
2369 RtlZeroMemory(pAdapterAddresses, requiredSize);
2370
2371 /* Let's set up the pointers */
2372 currentAddress = pAdapterAddresses;
2373 for (i = indexTable->numIndexes; i >= 0; i--)
2374 {
2375 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
2376 NULL,
2377 indexTable->indexes[i],
2378 &ifInfo)))
2379 {
2380 currentLocation = (PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES);
2381
2382 /* FIXME: Friendly name */
2383 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
2384 {
2385 currentAddress->FriendlyName = (PVOID)currentLocation;
2386 currentLocation += sizeof(WCHAR);
2387 }
2388
2389 /* Adapter name */
2390 currentAddress->AdapterName = (PVOID)currentLocation;
2391 currentLocation += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
2392
2393 /* Unicast address */
2394 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
2395 {
2396 currentAddress->FirstUnicastAddress = (PVOID)currentLocation;
2397 currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
2398 currentAddress->FirstUnicastAddress->Address.lpSockaddr = (PVOID)currentLocation;
2399 currentLocation += sizeof(struct sockaddr);
2400 }
2401
2402 /* FIXME: Implement multicast, anycast, and dns server stuff */
2403
2404 /* FIXME: Implement dns suffix and description */
2405 currentAddress->DnsSuffix = (PVOID)currentLocation;
2406 currentLocation += sizeof(WCHAR);
2407
2408 currentAddress->Description = (PVOID)currentLocation;
2409 currentLocation += sizeof(WCHAR);
2410
2411 currentAddress->Next = (PVOID)currentLocation;
2412
2413 /* We're only going to implement what's required for XP SP0 */
2414
2415 currentAddress = currentAddress->Next;
2416 }
2417 }
2418
2419 /* Terminate the last address correctly */
2420 if (currentAddress)
2421 currentAddress->Next = NULL;
2422
2423 /* Now again, for real this time */
2424
2425 currentAddress = pAdapterAddresses;
2426 for (i = indexTable->numIndexes; i >= 0; i--)
2427 {
2428 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
2429 NULL,
2430 indexTable->indexes[i],
2431 &ifInfo)))
2432 {
2433 /* Make sure we're not looping more than we hoped for */
2434 ASSERT(currentAddress);
2435
2436 /* Alignment information */
2437 currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES);
2438 currentAddress->IfIndex = indexTable->indexes[i];
2439
2440 /* Adapter name */
2441 strcpy(currentAddress->AdapterName, (char *)ifInfo.if_info.ent.if_descr);
2442
2443 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
2444 {
2445 currentAddress->FirstUnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
2446 currentAddress->FirstUnicastAddress->Flags = 0; //FIXME
2447 currentAddress->FirstUnicastAddress->Next = NULL; //FIXME: Support more than one address per adapter
2448 currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family = AF_INET;
2449 memcpy(currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data,
2450 &ifInfo.ip_addr.iae_addr,
2451 sizeof(ifInfo.ip_addr.iae_addr));
2452 currentAddress->FirstUnicastAddress->Address.iSockaddrLength = sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT);
2453 currentAddress->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther; //FIXME
2454 currentAddress->FirstUnicastAddress->SuffixOrigin = IpPrefixOriginOther; //FIXME
2455 currentAddress->FirstUnicastAddress->DadState = IpDadStatePreferred; //FIXME
2456 currentAddress->FirstUnicastAddress->ValidLifetime = 0xFFFFFFFF; //FIXME
2457 currentAddress->FirstUnicastAddress->PreferredLifetime = 0xFFFFFFFF; //FIXME
2458 currentAddress->FirstUnicastAddress->LeaseLifetime = 0xFFFFFFFF; //FIXME
2459 }
2460
2461 /* FIXME: Implement multicast, anycast, and dns server stuff */
2462 currentAddress->FirstAnycastAddress = NULL;
2463 currentAddress->FirstMulticastAddress = NULL;
2464 currentAddress->FirstDnsServerAddress = NULL;
2465
2466 /* FIXME: Implement dns suffix, description, and friendly name */
2467 currentAddress->DnsSuffix[0] = UNICODE_NULL;
2468 currentAddress->Description[0] = UNICODE_NULL;
2469 currentAddress->FriendlyName[0] = UNICODE_NULL;
2470
2471 /* Physical Address */
2472 memcpy(currentAddress->PhysicalAddress, ifInfo.if_info.ent.if_physaddr, ifInfo.if_info.ent.if_physaddrlen);
2473 currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen;
2474
2475 /* Flags */
2476 currentAddress->Flags = 0; //FIXME
2477
2478 /* MTU */
2479 currentAddress->Mtu = ifInfo.if_info.ent.if_mtu;
2480
2481 /* Interface type */
2482 currentAddress->IfType = ifInfo.if_info.ent.if_type;
2483
2484 /* Operational status */
2485 currentAddress->OperStatus = ifInfo.if_info.ent.if_operstatus;
2486
2487 /* We're only going to implement what's required for XP SP0 */
2488
2489 /* Move to the next address */
2490 currentAddress = currentAddress->Next;
2491 }
2492 }
2493
2494 closeTcpFile(tcpFile);
2495 free(indexTable);
2496
2497 return NO_ERROR;
2498 #else
2499 if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
2500 if (!pAdapterAddresses || *pOutBufLen == 0)
2501 return ERROR_BUFFER_OVERFLOW;
2502 if (Reserved) return ERROR_INVALID_PARAMETER;
2503
2504 FIXME(":stub\n");
2505 return ERROR_NO_DATA;
2506 #endif
2507 }
2508
2509 /*
2510 * @unimplemented
2511 */
2512 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
2513 {
2514 FIXME(":stub\n");
2515 return 0L;
2516 }
2517
2518 /*
2519 * @unimplemented
2520 */
2521 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
2522 {
2523 FIXME(":stub\n");
2524 return 0L;
2525 }
2526
2527 /*
2528 * @unimplemented
2529 */
2530 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
2531 {
2532 FIXME(":stub\n");
2533 return 0L;
2534 }
2535
2536 /*
2537 * @unimplemented
2538 */
2539 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
2540 {
2541 FIXME(":stub\n");
2542 return 0L;
2543 }
2544
2545 /******************************************************************
2546 * GetIfTable2 (IPHLPAPI.@)
2547 *
2548 * PARAMS
2549 * pIfTable [In/Out]
2550 */
2551
2552 NETIOAPI_API WINAPI GetIfTable2(PMIB_IF_TABLE2 *pIfTable)
2553 {
2554 UNIMPLEMENTED;
2555 return ERROR_NOT_SUPPORTED;
2556 }
2557
2558 /******************************************************************
2559 * GetIfEntry2 (IPHLPAPI.@)
2560 *
2561 * PARAMS
2562 * pIfRow [In/Out]
2563 */
2564 NETIOAPI_API WINAPI GetIfEntry2(IN OUT PMIB_IF_ROW2 pIfRow)
2565 {
2566 TRACE("pIfRow %p\n", pIfRow);
2567 if (!pIfRow)
2568 return ERROR_INVALID_PARAMETER;
2569
2570 UNIMPLEMENTED;
2571 return ERROR_NOT_SUPPORTED;
2572 }
2573
2574 DWORD WINAPI
2575 SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute)
2576 {
2577 FIXME("SetIpForwardEntryToStack() stub\n");
2578 return 0L;
2579 }
2580
2581 DWORD WINAPI
2582 NhGetInterfaceNameFromDeviceGuid(DWORD dwUnknown1,
2583 DWORD dwUnknown2,
2584 DWORD dwUnknown3,
2585 DWORD dwUnknown4,
2586 DWORD dwUnknown5)
2587 {
2588 FIXME("NhGetInterfaceNameFromDeviceGuid() stub\n");
2589 return 0L;
2590 }