sync with trunk r47227
[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 "dhcp/rosdhcp_public.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 = NO_ERROR;
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 pTcpTable = getTcpTable();
1768 if (pTcpTable)
1769 {
1770 size = sizeof(MIB_TCPTABLE);
1771 if (pTcpTable->dwNumEntries > 1)
1772 size += (pTcpTable->dwNumEntries - 1) * sizeof(MIB_TCPROW);
1773 *pdwSize = size;
1774
1775 if (bOrder)
1776 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1777 sizeof(MIB_TCPROW), TcpTableSorter);
1778 ret = NO_ERROR;
1779 }
1780 }
1781 }
1782 TRACE("returning %d\n", ret);
1783 return ret;
1784 }
1785
1786
1787 /******************************************************************
1788 * GetUdpStatisticsEx (IPHLPAPI.@)
1789 *
1790 *
1791 * PARAMS
1792 *
1793 * pStats [In/Out]
1794 * dwFamily [In]
1795 *
1796 * RETURNS
1797 *
1798 * DWORD
1799 *
1800 */
1801 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
1802 {
1803 DWORD ret;
1804
1805 TRACE("pStats %p\n", pStats);
1806 ret = getUDPStats(pStats, dwFamily);
1807 TRACE("returning %ld\n", ret);
1808 return ret;
1809 }
1810
1811 /******************************************************************
1812 * GetUdpStatistics (IPHLPAPI.@)
1813 *
1814 *
1815 * PARAMS
1816 *
1817 * pStats [In/Out]
1818 *
1819 * RETURNS
1820 *
1821 * DWORD
1822 *
1823 */
1824 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1825 {
1826 return GetUdpStatisticsEx(pStats, PF_INET);
1827 }
1828
1829
1830 static int UdpTableSorter(const void *a, const void *b)
1831 {
1832 int ret;
1833
1834 if (a && b) {
1835 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1836
1837 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1838 if (ret == 0)
1839 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1840 }
1841 else
1842 ret = 0;
1843 return ret;
1844 }
1845
1846
1847 /******************************************************************
1848 * GetUdpTable (IPHLPAPI.@)
1849 *
1850 *
1851 * PARAMS
1852 *
1853 * pUdpTable [In/Out]
1854 * pdwSize [In/Out]
1855 * bOrder [In]
1856 *
1857 * RETURNS
1858 *
1859 * DWORD
1860 *
1861 */
1862 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1863 {
1864 DWORD ret;
1865
1866 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
1867 (DWORD)bOrder);
1868 if (!pdwSize)
1869 ret = ERROR_INVALID_PARAMETER;
1870 else {
1871 DWORD numEntries = getNumUdpEntries();
1872 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1873
1874 if (!pUdpTable || *pdwSize < size) {
1875 *pdwSize = size;
1876 ret = ERROR_INSUFFICIENT_BUFFER;
1877 }
1878 else {
1879 PMIB_UDPTABLE table = getUdpTable();
1880
1881 if (table) {
1882 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1883 sizeof(MIB_UDPROW);
1884 if (*pdwSize < size) {
1885 *pdwSize = size;
1886 ret = ERROR_INSUFFICIENT_BUFFER;
1887 }
1888 else {
1889 memcpy(pUdpTable, table, size);
1890 if (bOrder)
1891 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1892 sizeof(MIB_UDPROW), UdpTableSorter);
1893 ret = NO_ERROR;
1894 }
1895 free(table);
1896 }
1897 else
1898 ret = ERROR_OUTOFMEMORY;
1899 }
1900 }
1901 TRACE("returning %ld\n", ret);
1902 return ret;
1903 }
1904
1905
1906 /******************************************************************
1907 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1908 *
1909 * This is a Win98-only function to get information on "unidirectional"
1910 * adapters. Since this is pretty nonsensical in other contexts, it
1911 * never returns anything.
1912 *
1913 * PARAMS
1914 * pIPIfInfo [Out] buffer for adapter infos
1915 * dwOutBufLen [Out] length of the output buffer
1916 *
1917 * RETURNS
1918 * Success: NO_ERROR
1919 * Failure: error code from winerror.h
1920 *
1921 * FIXME
1922 * Stub, returns ERROR_NOT_SUPPORTED.
1923 */
1924 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1925 {
1926 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
1927 /* a unidirectional adapter?? not bloody likely! */
1928 return ERROR_NOT_SUPPORTED;
1929 }
1930
1931
1932 /******************************************************************
1933 * IpReleaseAddress (IPHLPAPI.@)
1934 *
1935 * Release an IP obtained through DHCP,
1936 *
1937 * PARAMS
1938 * AdapterInfo [In] adapter to release IP address
1939 *
1940 * RETURNS
1941 * Success: NO_ERROR
1942 * Failure: error code from winerror.h
1943 *
1944 */
1945 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1946 {
1947 COMM_DHCP_REPLY Reply;
1948 COMM_DHCP_REQ Request;
1949 DWORD BytesRead;
1950
1951 Request.AdapterIndex = AdapterInfo->Index;
1952 Request.Type = DhcpReqReleaseIpAddress;
1953
1954 TRACE("AdapterInfo %p\n", AdapterInfo);
1955
1956 if (CallNamedPipe(DHCP_PIPE_NAME,
1957 &Request,
1958 sizeof(Request),
1959 &Reply,
1960 sizeof(Reply),
1961 &BytesRead,
1962 NMPWAIT_USE_DEFAULT_WAIT))
1963 {
1964 if (Reply.Reply)
1965 return NO_ERROR;
1966
1967 return ERROR_INVALID_PARAMETER;
1968 }
1969
1970 return ERROR_PROC_NOT_FOUND;
1971 }
1972
1973
1974 /******************************************************************
1975 * IpRenewAddress (IPHLPAPI.@)
1976 *
1977 * Renew an IP obtained through DHCP.
1978 *
1979 * PARAMS
1980 * AdapterInfo [In] adapter to renew IP address
1981 *
1982 * RETURNS
1983 * Success: NO_ERROR
1984 * Failure: error code from winerror.h
1985 */
1986 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1987 {
1988 COMM_DHCP_REPLY Reply;
1989 COMM_DHCP_REQ Request;
1990 DWORD BytesRead;
1991
1992 Request.AdapterIndex = AdapterInfo->Index;
1993 Request.Type = DhcpReqRenewIpAddress;
1994
1995 TRACE("AdapterInfo %p\n", AdapterInfo);
1996
1997 if (CallNamedPipe(DHCP_PIPE_NAME,
1998 &Request,
1999 sizeof(Request),
2000 &Reply,
2001 sizeof(Reply),
2002 &BytesRead,
2003 NMPWAIT_USE_DEFAULT_WAIT))
2004 {
2005 if (Reply.Reply)
2006 return NO_ERROR;
2007
2008 return ERROR_INVALID_PARAMETER;
2009 }
2010
2011 return ERROR_PROC_NOT_FOUND;
2012 }
2013
2014
2015 /******************************************************************
2016 * NotifyAddrChange (IPHLPAPI.@)
2017 *
2018 * Notify caller whenever the ip-interface map is changed.
2019 *
2020 * PARAMS
2021 * Handle [Out] handle usable in asynchronous notification
2022 * overlapped [In] overlapped structure that notifies the caller
2023 *
2024 * RETURNS
2025 * Success: NO_ERROR
2026 * Failure: error code from winerror.h
2027 *
2028 * FIXME
2029 * Stub, returns ERROR_NOT_SUPPORTED.
2030 */
2031 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2032 {
2033 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2034 return ERROR_NOT_SUPPORTED;
2035 }
2036
2037
2038 /******************************************************************
2039 * NotifyRouteChange (IPHLPAPI.@)
2040 *
2041 * Notify caller whenever the ip routing table is changed.
2042 *
2043 * PARAMS
2044 * Handle [Out] handle usable in asynchronous notification
2045 * overlapped [In] overlapped structure that notifies the caller
2046 *
2047 * RETURNS
2048 * Success: NO_ERROR
2049 * Failure: error code from winerror.h
2050 *
2051 * FIXME
2052 * Stub, returns ERROR_NOT_SUPPORTED.
2053 */
2054 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2055 {
2056 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2057 return ERROR_NOT_SUPPORTED;
2058 }
2059
2060
2061 /******************************************************************
2062 * SendARP (IPHLPAPI.@)
2063 *
2064 * Send an ARP request.
2065 *
2066 * PARAMS
2067 * DestIP [In] attempt to obtain this IP
2068 * SrcIP [In] optional sender IP address
2069 * pMacAddr [Out] buffer for the mac address
2070 * PhyAddrLen [In/Out] length of the output buffer
2071 *
2072 * RETURNS
2073 * Success: NO_ERROR
2074 * Failure: error code from winerror.h
2075 *
2076 * FIXME
2077 * Stub, returns ERROR_NOT_SUPPORTED.
2078 */
2079 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
2080 {
2081 FIXME("(DestIP 0x%08x, SrcIP 0x%08x, pMacAddr %p, PhyAddrLen %p): stub\n",
2082 DestIP, SrcIP, pMacAddr, PhyAddrLen);
2083 return ERROR_NOT_SUPPORTED;
2084 }
2085
2086
2087 /******************************************************************
2088 * SetIfEntry (IPHLPAPI.@)
2089 *
2090 * Set the administrative status of an interface.
2091 *
2092 * PARAMS
2093 * pIfRow [In] dwAdminStatus member specifies the new status.
2094 *
2095 * RETURNS
2096 * Success: NO_ERROR
2097 * Failure: error code from winerror.h
2098 *
2099 * FIXME
2100 * Stub, returns ERROR_NOT_SUPPORTED.
2101 */
2102 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
2103 {
2104 FIXME("(pIfRow %p): stub\n", pIfRow);
2105 /* this is supposed to set an interface administratively up or down.
2106 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
2107 this sort of down is indistinguishable from other sorts of down (e.g. no
2108 link). */
2109 return ERROR_NOT_SUPPORTED;
2110 }
2111
2112
2113 /******************************************************************
2114 * SetIpForwardEntry (IPHLPAPI.@)
2115 *
2116 * Modify an existing route.
2117 *
2118 * PARAMS
2119 * pRoute [In] route with the new information
2120 *
2121 * RETURNS
2122 * Success: NO_ERROR
2123 * Failure: error code from winerror.h
2124 *
2125 */
2126 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
2127 {
2128 return setIpForwardEntry( pRoute );
2129 }
2130
2131
2132 /******************************************************************
2133 * SetIpNetEntry (IPHLPAPI.@)
2134 *
2135 * Modify an existing ARP entry.
2136 *
2137 * PARAMS
2138 * pArpEntry [In] ARP entry with the new information
2139 *
2140 * RETURNS
2141 * Success: NO_ERROR
2142 * Failure: error code from winerror.h
2143 */
2144 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
2145 {
2146 HANDLE tcpFile;
2147 NTSTATUS status;
2148 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req =
2149 TCP_REQUEST_SET_INFORMATION_INIT;
2150 TDIEntityID id;
2151 DWORD returnSize;
2152 PMIB_IPNETROW arpBuff;
2153
2154 if (!pArpEntry)
2155 return ERROR_INVALID_PARAMETER;
2156
2157 if (!NT_SUCCESS(openTcpFile( &tcpFile )))
2158 return ERROR_NOT_SUPPORTED;
2159
2160 if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id )))
2161 {
2162 closeTcpFile(tcpFile);
2163 return ERROR_INVALID_PARAMETER;
2164 }
2165
2166 req.Req.ID.toi_class = INFO_CLASS_PROTOCOL;
2167 req.Req.ID.toi_type = INFO_TYPE_PROVIDER;
2168 req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID;
2169 req.Req.ID.toi_entity.tei_instance = id.tei_instance;
2170 req.Req.ID.toi_entity.tei_entity = AT_ENTITY;
2171 req.Req.BufferSize = sizeof(MIB_IPNETROW);
2172 arpBuff = (PMIB_IPNETROW)&req.Req.Buffer[0];
2173
2174 RtlCopyMemory(arpBuff, pArpEntry, sizeof(MIB_IPNETROW));
2175
2176 status = DeviceIoControl( tcpFile,
2177 IOCTL_TCP_SET_INFORMATION_EX,
2178 &req,
2179 sizeof(req),
2180 NULL,
2181 0,
2182 &returnSize,
2183 NULL );
2184
2185 closeTcpFile(tcpFile);
2186
2187 if (status)
2188 return NO_ERROR;
2189 else
2190 return ERROR_INVALID_PARAMETER;
2191 }
2192
2193
2194 /******************************************************************
2195 * SetIpStatistics (IPHLPAPI.@)
2196 *
2197 * Toggle IP forwarding and det the default TTL value.
2198 *
2199 * PARAMS
2200 * pIpStats [In] IP statistics with the new information
2201 *
2202 * RETURNS
2203 * Success: NO_ERROR
2204 * Failure: error code from winerror.h
2205 *
2206 * FIXME
2207 * Stub, returns NO_ERROR.
2208 */
2209 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
2210 {
2211 FIXME("(pIpStats %p): stub\n", pIpStats);
2212 return 0;
2213 }
2214
2215
2216 /******************************************************************
2217 * SetIpTTL (IPHLPAPI.@)
2218 *
2219 * Set the default TTL value.
2220 *
2221 * PARAMS
2222 * nTTL [In] new TTL value
2223 *
2224 * RETURNS
2225 * Success: NO_ERROR
2226 * Failure: error code from winerror.h
2227 *
2228 * FIXME
2229 * Stub, returns NO_ERROR.
2230 */
2231 DWORD WINAPI SetIpTTL(UINT nTTL)
2232 {
2233 FIXME("(nTTL %d): stub\n", nTTL);
2234 return 0;
2235 }
2236
2237
2238 /******************************************************************
2239 * SetTcpEntry (IPHLPAPI.@)
2240 *
2241 * Set the state of a TCP connection.
2242 *
2243 * PARAMS
2244 * pTcpRow [In] specifies connection with new state
2245 *
2246 * RETURNS
2247 * Success: NO_ERROR
2248 * Failure: error code from winerror.h
2249 *
2250 * FIXME
2251 * Stub, returns NO_ERROR.
2252 */
2253 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
2254 {
2255 FIXME("(pTcpRow %p): stub\n", pTcpRow);
2256 return 0;
2257 }
2258
2259
2260 /******************************************************************
2261 * UnenableRouter (IPHLPAPI.@)
2262 *
2263 * Decrement the IP-forwarding reference count. Turn off IP-forwarding
2264 * if it reaches zero.
2265 *
2266 * PARAMS
2267 * pOverlapped [In/Out] should be the same as in EnableRouter()
2268 * lpdwEnableCount [Out] optional, receives reference count
2269 *
2270 * RETURNS
2271 * Success: NO_ERROR
2272 * Failure: error code from winerror.h
2273 *
2274 * FIXME
2275 * Stub, returns ERROR_NOT_SUPPORTED.
2276 */
2277 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
2278 {
2279 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped,
2280 lpdwEnableCount);
2281 return ERROR_NOT_SUPPORTED;
2282 }
2283
2284 /*
2285 * @unimplemented
2286 */
2287 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
2288 {
2289 FIXME(":stub\n");
2290 return 0L;
2291 }
2292
2293
2294 /*
2295 * @unimplemented
2296 */
2297 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
2298 {
2299 FIXME(":stub\n");
2300 return 0L;
2301 }
2302
2303 /*
2304 * @implemented
2305 */
2306 DWORD WINAPI GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
2307 {
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 }
2495
2496 /*
2497 * @unimplemented
2498 */
2499 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
2500 {
2501 FIXME(":stub\n");
2502 return 0L;
2503 }
2504
2505 /*
2506 * @unimplemented
2507 */
2508 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
2509 {
2510 FIXME(":stub\n");
2511 return 0L;
2512 }
2513
2514 /*
2515 * @unimplemented
2516 */
2517 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
2518 {
2519 FIXME(":stub\n");
2520 return 0L;
2521 }
2522
2523 /*
2524 * @unimplemented
2525 */
2526 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
2527 {
2528 FIXME(":stub\n");
2529 return 0L;
2530 }
2531
2532 /******************************************************************
2533 * GetIfTable2 (IPHLPAPI.@)
2534 *
2535 * PARAMS
2536 * pIfTable [In/Out]
2537 */
2538
2539 NETIOAPI_API WINAPI GetIfTable2(PMIB_IF_TABLE2 *pIfTable)
2540 {
2541 UNIMPLEMENTED;
2542 return ERROR_NOT_SUPPORTED;
2543 }
2544
2545 /******************************************************************
2546 * GetIfEntry2 (IPHLPAPI.@)
2547 *
2548 * PARAMS
2549 * pIfRow [In/Out]
2550 */
2551 NETIOAPI_API WINAPI GetIfEntry2(IN OUT PMIB_IF_ROW2 pIfRow)
2552 {
2553 TRACE("pIfRow %p\n", pIfRow);
2554 if (!pIfRow)
2555 return ERROR_INVALID_PARAMETER;
2556
2557 UNIMPLEMENTED;
2558 return ERROR_NOT_SUPPORTED;
2559 }
2560
2561 DWORD WINAPI
2562 SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute)
2563 {
2564 FIXME("SetIpForwardEntryToStack() stub\n");
2565 return 0L;
2566 }
2567
2568 DWORD WINAPI
2569 NhGetInterfaceNameFromDeviceGuid(DWORD dwUnknown1,
2570 DWORD dwUnknown2,
2571 DWORD dwUnknown3,
2572 DWORD dwUnknown4,
2573 DWORD dwUnknown5)
2574 {
2575 FIXME("NhGetInterfaceNameFromDeviceGuid() stub\n");
2576 return 0L;
2577 }