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