[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"DHCPNameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
1626 {
1627 pPerAdapterInfo->AutoconfigActive = TRUE;
1628 }
1629
1630 RegCloseKey(hkey);
1631 return NOERROR;
1632 }
1633
1634
1635 /******************************************************************
1636 * GetRTTAndHopCount (IPHLPAPI.@)
1637 *
1638 *
1639 * PARAMS
1640 *
1641 * DestIpAddress [In]
1642 * HopCount [In/Out]
1643 * MaxHops [In]
1644 * RTT [In/Out]
1645 *
1646 * RETURNS
1647 *
1648 * BOOL
1649 *
1650 */
1651 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
1652 {
1653 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
1654 DestIpAddress, HopCount, MaxHops, RTT);
1655 FIXME(":stub\n");
1656 return (BOOL) 0;
1657 }
1658
1659
1660 /******************************************************************
1661 * GetTcpStatisticsEx (IPHLPAPI.@)
1662 *
1663 *
1664 * PARAMS
1665 *
1666 * pStats [In/Out]
1667 * dwFamily [In]
1668 *
1669 * RETURNS
1670 *
1671 * DWORD
1672 *
1673 */
1674 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
1675 {
1676 DWORD ret;
1677
1678 TRACE("pStats %p\n", pStats);
1679 ret = getTCPStats(pStats, dwFamily);
1680 TRACE("returning %ld\n", ret);
1681 return ret;
1682 }
1683
1684 /******************************************************************
1685 * GetTcpStatistics (IPHLPAPI.@)
1686 *
1687 *
1688 * PARAMS
1689 *
1690 * pStats [In/Out]
1691 *
1692 * RETURNS
1693 *
1694 * DWORD
1695 *
1696 */
1697 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
1698 {
1699 return GetTcpStatisticsEx(pStats, PF_INET);
1700 }
1701
1702
1703 static int TcpTableSorter(const void *a, const void *b)
1704 {
1705 int ret;
1706
1707 if (a && b) {
1708 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
1709
1710 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1711 if (ret == 0) {
1712 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1713 if (ret == 0) {
1714 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
1715 if (ret == 0)
1716 ret = rowA->dwRemotePort - rowB->dwRemotePort;
1717 }
1718 }
1719 }
1720 else
1721 ret = 0;
1722 return ret;
1723 }
1724
1725
1726 /******************************************************************
1727 * GetTcpTable (IPHLPAPI.@)
1728 *
1729 * Get the table of active TCP connections.
1730 *
1731 * PARAMS
1732 * pTcpTable [Out] buffer for TCP connections table
1733 * pdwSize [In/Out] length of output buffer
1734 * bOrder [In] whether to order the table
1735 *
1736 * RETURNS
1737 * Success: NO_ERROR
1738 * Failure: error code from winerror.h
1739 *
1740 * NOTES
1741 * If pdwSize is less than required, the function will return
1742 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to
1743 * the required byte size.
1744 * If bOrder is true, the returned table will be sorted, first by
1745 * local address and port number, then by remote address and port
1746 * number.
1747 */
1748 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
1749 {
1750 DWORD ret = ERROR_NO_DATA;
1751
1752 TRACE("pTcpTable %p, pdwSize %p, bOrder %d\n", pTcpTable, pdwSize,
1753 (DWORD)bOrder);
1754 if (!pdwSize)
1755 ret = ERROR_INVALID_PARAMETER;
1756 else {
1757 DWORD numEntries = getNumTcpEntries();
1758 DWORD size = sizeof(MIB_TCPTABLE);
1759
1760 if (numEntries > 1)
1761 size += (numEntries - 1) * sizeof(MIB_TCPROW);
1762 if (!pTcpTable || *pdwSize < size) {
1763 *pdwSize = size;
1764 ret = ERROR_INSUFFICIENT_BUFFER;
1765 }
1766 else {
1767 PMIB_TCPTABLE pOurTcpTable = getTcpTable();
1768 if (pOurTcpTable)
1769 {
1770 size = sizeof(MIB_TCPTABLE);
1771 if (pOurTcpTable->dwNumEntries > 1)
1772 size += (pOurTcpTable->dwNumEntries - 1) * sizeof(MIB_TCPROW);
1773
1774 if (*pdwSize < size)
1775 {
1776 *pdwSize = size;
1777
1778 ret = ERROR_INSUFFICIENT_BUFFER;
1779 }
1780 else
1781 {
1782 memcpy(pTcpTable, pOurTcpTable, size);
1783
1784 if (bOrder)
1785 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1786 sizeof(MIB_TCPROW), TcpTableSorter);
1787
1788 ret = NO_ERROR;
1789 }
1790
1791 free(pOurTcpTable);
1792 }
1793 }
1794 }
1795 TRACE("returning %d\n", ret);
1796 return ret;
1797 }
1798
1799
1800 /******************************************************************
1801 * GetUdpStatisticsEx (IPHLPAPI.@)
1802 *
1803 *
1804 * PARAMS
1805 *
1806 * pStats [In/Out]
1807 * dwFamily [In]
1808 *
1809 * RETURNS
1810 *
1811 * DWORD
1812 *
1813 */
1814 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
1815 {
1816 DWORD ret;
1817
1818 TRACE("pStats %p\n", pStats);
1819 ret = getUDPStats(pStats, dwFamily);
1820 TRACE("returning %ld\n", ret);
1821 return ret;
1822 }
1823
1824 /******************************************************************
1825 * GetUdpStatistics (IPHLPAPI.@)
1826 *
1827 *
1828 * PARAMS
1829 *
1830 * pStats [In/Out]
1831 *
1832 * RETURNS
1833 *
1834 * DWORD
1835 *
1836 */
1837 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1838 {
1839 return GetUdpStatisticsEx(pStats, PF_INET);
1840 }
1841
1842
1843 static int UdpTableSorter(const void *a, const void *b)
1844 {
1845 int ret;
1846
1847 if (a && b) {
1848 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1849
1850 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1851 if (ret == 0)
1852 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1853 }
1854 else
1855 ret = 0;
1856 return ret;
1857 }
1858
1859
1860 /******************************************************************
1861 * GetUdpTable (IPHLPAPI.@)
1862 *
1863 *
1864 * PARAMS
1865 *
1866 * pUdpTable [In/Out]
1867 * pdwSize [In/Out]
1868 * bOrder [In]
1869 *
1870 * RETURNS
1871 *
1872 * DWORD
1873 *
1874 */
1875 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1876 {
1877 DWORD ret;
1878
1879 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
1880 (DWORD)bOrder);
1881 if (!pdwSize)
1882 ret = ERROR_INVALID_PARAMETER;
1883 else {
1884 DWORD numEntries = getNumUdpEntries();
1885 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1886
1887 if (!pUdpTable || *pdwSize < size) {
1888 *pdwSize = size;
1889 ret = ERROR_INSUFFICIENT_BUFFER;
1890 }
1891 else {
1892 PMIB_UDPTABLE table = getUdpTable();
1893
1894 if (table) {
1895 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1896 sizeof(MIB_UDPROW);
1897 if (*pdwSize < size) {
1898 *pdwSize = size;
1899 ret = ERROR_INSUFFICIENT_BUFFER;
1900 }
1901 else {
1902 memcpy(pUdpTable, table, size);
1903 if (bOrder)
1904 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1905 sizeof(MIB_UDPROW), UdpTableSorter);
1906 ret = NO_ERROR;
1907 }
1908 free(table);
1909 }
1910 else
1911 ret = ERROR_OUTOFMEMORY;
1912 }
1913 }
1914 TRACE("returning %ld\n", ret);
1915 return ret;
1916 }
1917
1918
1919 /******************************************************************
1920 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1921 *
1922 * This is a Win98-only function to get information on "unidirectional"
1923 * adapters. Since this is pretty nonsensical in other contexts, it
1924 * never returns anything.
1925 *
1926 * PARAMS
1927 * pIPIfInfo [Out] buffer for adapter infos
1928 * dwOutBufLen [Out] length of the output buffer
1929 *
1930 * RETURNS
1931 * Success: NO_ERROR
1932 * Failure: error code from winerror.h
1933 *
1934 * FIXME
1935 * Stub, returns ERROR_NOT_SUPPORTED.
1936 */
1937 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1938 {
1939 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
1940 /* a unidirectional adapter?? not bloody likely! */
1941 return ERROR_NOT_SUPPORTED;
1942 }
1943
1944
1945 /******************************************************************
1946 * IpReleaseAddress (IPHLPAPI.@)
1947 *
1948 * Release an IP obtained through DHCP,
1949 *
1950 * PARAMS
1951 * AdapterInfo [In] adapter to release IP address
1952 *
1953 * RETURNS
1954 * Success: NO_ERROR
1955 * Failure: error code from winerror.h
1956 *
1957 */
1958 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1959 {
1960 DWORD Status, Version = 0;
1961
1962 if (!AdapterInfo || !AdapterInfo->Name)
1963 return ERROR_INVALID_PARAMETER;
1964
1965 /* Maybe we should do this in DllMain */
1966 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
1967 return ERROR_PROC_NOT_FOUND;
1968
1969 if (DhcpReleaseIpAddressLease(AdapterInfo->Index))
1970 Status = ERROR_SUCCESS;
1971 else
1972 Status = ERROR_PROC_NOT_FOUND;
1973
1974 DhcpCApiCleanup();
1975
1976 return Status;
1977 }
1978
1979
1980 /******************************************************************
1981 * IpRenewAddress (IPHLPAPI.@)
1982 *
1983 * Renew an IP obtained through DHCP.
1984 *
1985 * PARAMS
1986 * AdapterInfo [In] adapter to renew IP address
1987 *
1988 * RETURNS
1989 * Success: NO_ERROR
1990 * Failure: error code from winerror.h
1991 */
1992 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1993 {
1994 DWORD Status, Version = 0;
1995
1996 if (!AdapterInfo || !AdapterInfo->Name)
1997 return ERROR_INVALID_PARAMETER;
1998
1999 /* Maybe we should do this in DllMain */
2000 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
2001 return ERROR_PROC_NOT_FOUND;
2002
2003 if (DhcpRenewIpAddressLease(AdapterInfo->Index))
2004 Status = ERROR_SUCCESS;
2005 else
2006 Status = ERROR_PROC_NOT_FOUND;
2007
2008 DhcpCApiCleanup();
2009
2010 return Status;
2011 }
2012
2013
2014 /******************************************************************
2015 * NotifyAddrChange (IPHLPAPI.@)
2016 *
2017 * Notify caller whenever the ip-interface map is changed.
2018 *
2019 * PARAMS
2020 * Handle [Out] handle usable in asynchronous notification
2021 * overlapped [In] overlapped structure that notifies the caller
2022 *
2023 * RETURNS
2024 * Success: NO_ERROR
2025 * Failure: error code from winerror.h
2026 *
2027 * FIXME
2028 * Stub, returns ERROR_NOT_SUPPORTED.
2029 */
2030 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2031 {
2032 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2033 return ERROR_NOT_SUPPORTED;
2034 }
2035
2036
2037 /******************************************************************
2038 * NotifyRouteChange (IPHLPAPI.@)
2039 *
2040 * Notify caller whenever the ip routing table is changed.
2041 *
2042 * PARAMS
2043 * Handle [Out] handle usable in asynchronous notification
2044 * overlapped [In] overlapped structure that notifies the caller
2045 *
2046 * RETURNS
2047 * Success: NO_ERROR
2048 * Failure: error code from winerror.h
2049 *
2050 * FIXME
2051 * Stub, returns ERROR_NOT_SUPPORTED.
2052 */
2053 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2054 {
2055 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2056 return ERROR_NOT_SUPPORTED;
2057 }
2058
2059
2060 /******************************************************************
2061 * SendARP (IPHLPAPI.@)
2062 *
2063 * Send an ARP request.
2064 *
2065 * PARAMS
2066 * DestIP [In] attempt to obtain this IP
2067 * SrcIP [In] optional sender IP address
2068 * pMacAddr [Out] buffer for the mac address
2069 * PhyAddrLen [In/Out] length of the output buffer
2070 *
2071 * RETURNS
2072 * Success: NO_ERROR
2073 * Failure: error code from winerror.h
2074 *
2075 * FIXME
2076 * Stub, returns ERROR_NOT_SUPPORTED.
2077 */
2078 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
2079 {
2080 FIXME("(DestIP 0x%08x, SrcIP 0x%08x, pMacAddr %p, PhyAddrLen %p): stub\n",
2081 DestIP, SrcIP, pMacAddr, PhyAddrLen);
2082 return ERROR_NOT_SUPPORTED;
2083 }
2084
2085
2086 /******************************************************************
2087 * SetIfEntry (IPHLPAPI.@)
2088 *
2089 * Set the administrative status of an interface.
2090 *
2091 * PARAMS
2092 * pIfRow [In] dwAdminStatus member specifies the new status.
2093 *
2094 * RETURNS
2095 * Success: NO_ERROR
2096 * Failure: error code from winerror.h
2097 *
2098 * FIXME
2099 * Stub, returns ERROR_NOT_SUPPORTED.
2100 */
2101 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
2102 {
2103 FIXME("(pIfRow %p): stub\n", pIfRow);
2104 /* this is supposed to set an interface administratively up or down.
2105 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
2106 this sort of down is indistinguishable from other sorts of down (e.g. no
2107 link). */
2108 return ERROR_NOT_SUPPORTED;
2109 }
2110
2111
2112 /******************************************************************
2113 * SetIpForwardEntry (IPHLPAPI.@)
2114 *
2115 * Modify an existing route.
2116 *
2117 * PARAMS
2118 * pRoute [In] route with the new information
2119 *
2120 * RETURNS
2121 * Success: NO_ERROR
2122 * Failure: error code from winerror.h
2123 *
2124 */
2125 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
2126 {
2127 return setIpForwardEntry( pRoute );
2128 }
2129
2130
2131 /******************************************************************
2132 * SetIpNetEntry (IPHLPAPI.@)
2133 *
2134 * Modify an existing ARP entry.
2135 *
2136 * PARAMS
2137 * pArpEntry [In] ARP entry with the new information
2138 *
2139 * RETURNS
2140 * Success: NO_ERROR
2141 * Failure: error code from winerror.h
2142 */
2143 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
2144 {
2145 HANDLE tcpFile;
2146 NTSTATUS status;
2147 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req =
2148 TCP_REQUEST_SET_INFORMATION_INIT;
2149 TDIEntityID id;
2150 DWORD returnSize;
2151 PMIB_IPNETROW arpBuff;
2152
2153 if (!pArpEntry)
2154 return ERROR_INVALID_PARAMETER;
2155
2156 if (!NT_SUCCESS(openTcpFile( &tcpFile )))
2157 return ERROR_NOT_SUPPORTED;
2158
2159 if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id )))
2160 {
2161 closeTcpFile(tcpFile);
2162 return ERROR_INVALID_PARAMETER;
2163 }
2164
2165 req.Req.ID.toi_class = INFO_CLASS_PROTOCOL;
2166 req.Req.ID.toi_type = INFO_TYPE_PROVIDER;
2167 req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID;
2168 req.Req.ID.toi_entity.tei_instance = id.tei_instance;
2169 req.Req.ID.toi_entity.tei_entity = AT_ENTITY;
2170 req.Req.BufferSize = sizeof(MIB_IPNETROW);
2171 arpBuff = (PMIB_IPNETROW)&req.Req.Buffer[0];
2172
2173 RtlCopyMemory(arpBuff, pArpEntry, sizeof(MIB_IPNETROW));
2174
2175 status = DeviceIoControl( tcpFile,
2176 IOCTL_TCP_SET_INFORMATION_EX,
2177 &req,
2178 sizeof(req),
2179 NULL,
2180 0,
2181 &returnSize,
2182 NULL );
2183
2184 closeTcpFile(tcpFile);
2185
2186 if (status)
2187 return NO_ERROR;
2188 else
2189 return ERROR_INVALID_PARAMETER;
2190 }
2191
2192
2193 /******************************************************************
2194 * SetIpStatistics (IPHLPAPI.@)
2195 *
2196 * Toggle IP forwarding and det the default TTL value.
2197 *
2198 * PARAMS
2199 * pIpStats [In] IP statistics with the new information
2200 *
2201 * RETURNS
2202 * Success: NO_ERROR
2203 * Failure: error code from winerror.h
2204 *
2205 * FIXME
2206 * Stub, returns NO_ERROR.
2207 */
2208 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
2209 {
2210 FIXME("(pIpStats %p): stub\n", pIpStats);
2211 return 0;
2212 }
2213
2214
2215 /******************************************************************
2216 * SetIpTTL (IPHLPAPI.@)
2217 *
2218 * Set the default TTL value.
2219 *
2220 * PARAMS
2221 * nTTL [In] new TTL value
2222 *
2223 * RETURNS
2224 * Success: NO_ERROR
2225 * Failure: error code from winerror.h
2226 *
2227 * FIXME
2228 * Stub, returns NO_ERROR.
2229 */
2230 DWORD WINAPI SetIpTTL(UINT nTTL)
2231 {
2232 FIXME("(nTTL %d): stub\n", nTTL);
2233 return 0;
2234 }
2235
2236
2237 /******************************************************************
2238 * SetTcpEntry (IPHLPAPI.@)
2239 *
2240 * Set the state of a TCP connection.
2241 *
2242 * PARAMS
2243 * pTcpRow [In] specifies connection with new state
2244 *
2245 * RETURNS
2246 * Success: NO_ERROR
2247 * Failure: error code from winerror.h
2248 *
2249 * FIXME
2250 * Stub, returns NO_ERROR.
2251 */
2252 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
2253 {
2254 FIXME("(pTcpRow %p): stub\n", pTcpRow);
2255 return 0;
2256 }
2257
2258
2259 /******************************************************************
2260 * UnenableRouter (IPHLPAPI.@)
2261 *
2262 * Decrement the IP-forwarding reference count. Turn off IP-forwarding
2263 * if it reaches zero.
2264 *
2265 * PARAMS
2266 * pOverlapped [In/Out] should be the same as in EnableRouter()
2267 * lpdwEnableCount [Out] optional, receives reference count
2268 *
2269 * RETURNS
2270 * Success: NO_ERROR
2271 * Failure: error code from winerror.h
2272 *
2273 * FIXME
2274 * Stub, returns ERROR_NOT_SUPPORTED.
2275 */
2276 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
2277 {
2278 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped,
2279 lpdwEnableCount);
2280 return ERROR_NOT_SUPPORTED;
2281 }
2282
2283 /*
2284 * @unimplemented
2285 */
2286 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
2287 {
2288 FIXME(":stub\n");
2289 return 0L;
2290 }
2291
2292
2293 /*
2294 * @unimplemented
2295 */
2296 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
2297 {
2298 FIXME(":stub\n");
2299 return 0L;
2300 }
2301
2302 /*
2303 * @implemented
2304 */
2305 DWORD WINAPI GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
2306 {
2307 #if 0
2308 InterfaceIndexTable *indexTable;
2309 IFInfo ifInfo;
2310 int i;
2311 ULONG ret, requiredSize = 0;
2312 PIP_ADAPTER_ADDRESSES currentAddress;
2313 PUCHAR currentLocation;
2314 HANDLE tcpFile;
2315
2316 if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
2317 if (Reserved) return ERROR_INVALID_PARAMETER;
2318
2319 indexTable = getNonLoopbackInterfaceIndexTable(); //I think we want non-loopback here
2320 if (!indexTable)
2321 return ERROR_NOT_ENOUGH_MEMORY;
2322
2323 ret = openTcpFile(&tcpFile);
2324 if (!NT_SUCCESS(ret))
2325 return ERROR_NO_DATA;
2326
2327 for (i = indexTable->numIndexes; i >= 0; i--)
2328 {
2329 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
2330 NULL,
2331 indexTable->indexes[i],
2332 &ifInfo)))
2333 {
2334 /* The whole struct */
2335 requiredSize += sizeof(IP_ADAPTER_ADDRESSES);
2336
2337 /* Friendly name */
2338 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
2339 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1; //FIXME
2340
2341 /* Adapter name */
2342 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
2343
2344 /* Unicast address */
2345 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
2346 requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
2347
2348 /* FIXME: Implement multicast, anycast, and dns server stuff */
2349
2350 /* FIXME: Implement dns suffix and description */
2351 requiredSize += 2 * sizeof(WCHAR);
2352
2353 /* We're only going to implement what's required for XP SP0 */
2354 }
2355 }
2356
2357 if (*pOutBufLen < requiredSize)
2358 {
2359 *pOutBufLen = requiredSize;
2360 closeTcpFile(tcpFile);
2361 free(indexTable);
2362 return ERROR_BUFFER_OVERFLOW;
2363 }
2364
2365 RtlZeroMemory(pAdapterAddresses, requiredSize);
2366
2367 /* Let's set up the pointers */
2368 currentAddress = pAdapterAddresses;
2369 for (i = indexTable->numIndexes; i >= 0; i--)
2370 {
2371 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
2372 NULL,
2373 indexTable->indexes[i],
2374 &ifInfo)))
2375 {
2376 currentLocation = (PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES);
2377
2378 /* FIXME: Friendly name */
2379 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
2380 {
2381 currentAddress->FriendlyName = (PVOID)currentLocation;
2382 currentLocation += sizeof(WCHAR);
2383 }
2384
2385 /* Adapter name */
2386 currentAddress->AdapterName = (PVOID)currentLocation;
2387 currentLocation += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
2388
2389 /* Unicast address */
2390 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
2391 {
2392 currentAddress->FirstUnicastAddress = (PVOID)currentLocation;
2393 currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
2394 currentAddress->FirstUnicastAddress->Address.lpSockaddr = (PVOID)currentLocation;
2395 currentLocation += sizeof(struct sockaddr);
2396 }
2397
2398 /* FIXME: Implement multicast, anycast, and dns server stuff */
2399
2400 /* FIXME: Implement dns suffix and description */
2401 currentAddress->DnsSuffix = (PVOID)currentLocation;
2402 currentLocation += sizeof(WCHAR);
2403
2404 currentAddress->Description = (PVOID)currentLocation;
2405 currentLocation += sizeof(WCHAR);
2406
2407 currentAddress->Next = (PVOID)currentLocation;
2408
2409 /* We're only going to implement what's required for XP SP0 */
2410
2411 currentAddress = currentAddress->Next;
2412 }
2413 }
2414
2415 /* Terminate the last address correctly */
2416 if (currentAddress)
2417 currentAddress->Next = NULL;
2418
2419 /* Now again, for real this time */
2420
2421 currentAddress = pAdapterAddresses;
2422 for (i = indexTable->numIndexes; i >= 0; i--)
2423 {
2424 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
2425 NULL,
2426 indexTable->indexes[i],
2427 &ifInfo)))
2428 {
2429 /* Make sure we're not looping more than we hoped for */
2430 ASSERT(currentAddress);
2431
2432 /* Alignment information */
2433 currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES);
2434 currentAddress->IfIndex = indexTable->indexes[i];
2435
2436 /* Adapter name */
2437 strcpy(currentAddress->AdapterName, (char *)ifInfo.if_info.ent.if_descr);
2438
2439 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
2440 {
2441 currentAddress->FirstUnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
2442 currentAddress->FirstUnicastAddress->Flags = 0; //FIXME
2443 currentAddress->FirstUnicastAddress->Next = NULL; //FIXME: Support more than one address per adapter
2444 currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family = AF_INET;
2445 memcpy(currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data,
2446 &ifInfo.ip_addr.iae_addr,
2447 sizeof(ifInfo.ip_addr.iae_addr));
2448 currentAddress->FirstUnicastAddress->Address.iSockaddrLength = sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT);
2449 currentAddress->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther; //FIXME
2450 currentAddress->FirstUnicastAddress->SuffixOrigin = IpPrefixOriginOther; //FIXME
2451 currentAddress->FirstUnicastAddress->DadState = IpDadStatePreferred; //FIXME
2452 currentAddress->FirstUnicastAddress->ValidLifetime = 0xFFFFFFFF; //FIXME
2453 currentAddress->FirstUnicastAddress->PreferredLifetime = 0xFFFFFFFF; //FIXME
2454 currentAddress->FirstUnicastAddress->LeaseLifetime = 0xFFFFFFFF; //FIXME
2455 }
2456
2457 /* FIXME: Implement multicast, anycast, and dns server stuff */
2458 currentAddress->FirstAnycastAddress = NULL;
2459 currentAddress->FirstMulticastAddress = NULL;
2460 currentAddress->FirstDnsServerAddress = NULL;
2461
2462 /* FIXME: Implement dns suffix, description, and friendly name */
2463 currentAddress->DnsSuffix[0] = UNICODE_NULL;
2464 currentAddress->Description[0] = UNICODE_NULL;
2465 currentAddress->FriendlyName[0] = UNICODE_NULL;
2466
2467 /* Physical Address */
2468 memcpy(currentAddress->PhysicalAddress, ifInfo.if_info.ent.if_physaddr, ifInfo.if_info.ent.if_physaddrlen);
2469 currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen;
2470
2471 /* Flags */
2472 currentAddress->Flags = 0; //FIXME
2473
2474 /* MTU */
2475 currentAddress->Mtu = ifInfo.if_info.ent.if_mtu;
2476
2477 /* Interface type */
2478 currentAddress->IfType = ifInfo.if_info.ent.if_type;
2479
2480 /* Operational status */
2481 currentAddress->OperStatus = ifInfo.if_info.ent.if_operstatus;
2482
2483 /* We're only going to implement what's required for XP SP0 */
2484
2485 /* Move to the next address */
2486 currentAddress = currentAddress->Next;
2487 }
2488 }
2489
2490 closeTcpFile(tcpFile);
2491 free(indexTable);
2492
2493 return NO_ERROR;
2494 #else
2495 if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
2496 if (!pAdapterAddresses || *pOutBufLen == 0)
2497 return ERROR_BUFFER_OVERFLOW;
2498 if (Reserved) return ERROR_INVALID_PARAMETER;
2499
2500 FIXME(":stub\n");
2501 return ERROR_NO_DATA;
2502 #endif
2503 }
2504
2505 /*
2506 * @unimplemented
2507 */
2508 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
2509 {
2510 FIXME(":stub\n");
2511 return 0L;
2512 }
2513
2514 /*
2515 * @unimplemented
2516 */
2517 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
2518 {
2519 FIXME(":stub\n");
2520 return 0L;
2521 }
2522
2523 /*
2524 * @unimplemented
2525 */
2526 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
2527 {
2528 FIXME(":stub\n");
2529 return 0L;
2530 }
2531
2532 /*
2533 * @unimplemented
2534 */
2535 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
2536 {
2537 FIXME(":stub\n");
2538 return 0L;
2539 }
2540
2541 /******************************************************************
2542 * GetIfTable2 (IPHLPAPI.@)
2543 *
2544 * PARAMS
2545 * pIfTable [In/Out]
2546 */
2547
2548 NETIOAPI_API WINAPI GetIfTable2(PMIB_IF_TABLE2 *pIfTable)
2549 {
2550 UNIMPLEMENTED;
2551 return ERROR_NOT_SUPPORTED;
2552 }
2553
2554 /******************************************************************
2555 * GetIfEntry2 (IPHLPAPI.@)
2556 *
2557 * PARAMS
2558 * pIfRow [In/Out]
2559 */
2560 NETIOAPI_API WINAPI GetIfEntry2(IN OUT PMIB_IF_ROW2 pIfRow)
2561 {
2562 TRACE("pIfRow %p\n", pIfRow);
2563 if (!pIfRow)
2564 return ERROR_INVALID_PARAMETER;
2565
2566 UNIMPLEMENTED;
2567 return ERROR_NOT_SUPPORTED;
2568 }
2569
2570 DWORD WINAPI
2571 SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute)
2572 {
2573 FIXME("SetIpForwardEntryToStack() stub\n");
2574 return 0L;
2575 }
2576
2577 DWORD WINAPI
2578 NhGetInterfaceNameFromDeviceGuid(DWORD dwUnknown1,
2579 DWORD dwUnknown2,
2580 DWORD dwUnknown3,
2581 DWORD dwUnknown4,
2582 DWORD dwUnknown5)
2583 {
2584 FIXME("NhGetInterfaceNameFromDeviceGuid() stub\n");
2585 return 0L;
2586 }