Create a branch for header work.
[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 /******************************************************************
794 * GetFriendlyIfIndex (IPHLPAPI.@)
795 *
796 *
797 * PARAMS
798 *
799 * IfIndex [In]
800 *
801 * RETURNS
802 *
803 * DWORD
804 *
805 */
806 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
807 {
808 /* windows doesn't validate these, either, just makes sure the top byte is
809 cleared. I assume my ifenum module never gives an index with the top
810 byte set. */
811 TRACE("returning %ld\n", IfIndex);
812 return IfIndex;
813 }
814
815
816 /******************************************************************
817 * GetIcmpStatistics (IPHLPAPI.@)
818 *
819 *
820 * PARAMS
821 *
822 * pStats [In/Out]
823 *
824 * RETURNS
825 *
826 * DWORD
827 *
828 */
829 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
830 {
831 DWORD ret;
832
833 TRACE("pStats %p\n", pStats);
834 ret = getICMPStats(pStats);
835 TRACE("returning %ld\n", ret);
836 return ret;
837 }
838
839
840 /******************************************************************
841 * GetIfEntry (IPHLPAPI.@)
842 *
843 *
844 * PARAMS
845 *
846 * pIfRow [In/Out]
847 *
848 * RETURNS
849 *
850 * DWORD
851 *
852 */
853 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
854 {
855 DWORD ret;
856 const char *name;
857
858 TRACE("pIfRow %p\n", pIfRow);
859 if (!pIfRow)
860 return ERROR_INVALID_PARAMETER;
861
862 name = getInterfaceNameByIndex(pIfRow->dwIndex);
863 if (name) {
864 ret = getInterfaceEntryByIndex(pIfRow->dwIndex, pIfRow);
865 if (ret == NO_ERROR)
866 ret = getInterfaceStatsByName(name, pIfRow);
867 consumeInterfaceName(name);
868 }
869 else
870 ret = ERROR_INVALID_DATA;
871 TRACE("returning %ld\n", ret);
872 return ret;
873 }
874
875
876 static int IfTableSorter(const void *a, const void *b)
877 {
878 int ret;
879
880 if (a && b)
881 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex;
882 else
883 ret = 0;
884 return ret;
885 }
886
887
888 /******************************************************************
889 * GetIfTable (IPHLPAPI.@)
890 *
891 *
892 * PARAMS
893 *
894 * pIfTable [In/Out]
895 * pdwSize [In/Out]
896 * bOrder [In]
897 *
898 * RETURNS
899 *
900 * DWORD
901 *
902 */
903 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
904 {
905 DWORD ret;
906
907 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize,
908 (DWORD)bOrder);
909 if (!pdwSize)
910 ret = ERROR_INVALID_PARAMETER;
911 else {
912 DWORD numInterfaces = getNumInterfaces();
913 ULONG size;
914 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces);
915 size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW);
916
917 if (!pIfTable || *pdwSize < size) {
918 *pdwSize = size;
919 ret = ERROR_INSUFFICIENT_BUFFER;
920 }
921 else {
922 InterfaceIndexTable *table = getInterfaceIndexTable();
923
924 if (table) {
925 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) *
926 sizeof(MIB_IFROW);
927 if (*pdwSize < size) {
928 *pdwSize = size;
929 ret = ERROR_INSUFFICIENT_BUFFER;
930 }
931 else {
932 DWORD ndx;
933
934 pIfTable->dwNumEntries = 0;
935 for (ndx = 0; ndx < table->numIndexes; ndx++) {
936 pIfTable->table[ndx].dwIndex = table->indexes[ndx];
937 GetIfEntry(&pIfTable->table[ndx]);
938 pIfTable->dwNumEntries++;
939 }
940 if (bOrder)
941 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
942 IfTableSorter);
943 ret = NO_ERROR;
944 }
945 free(table);
946 }
947 else
948 ret = ERROR_OUTOFMEMORY;
949 }
950 }
951 TRACE("returning %ld\n", ret);
952 return ret;
953 }
954
955
956 /******************************************************************
957 * GetInterfaceInfo (IPHLPAPI.@)
958 *
959 *
960 * PARAMS
961 *
962 * pIfTable [In/Out]
963 * dwOutBufLen [In/Out]
964 *
965 * RETURNS
966 *
967 * DWORD
968 *
969 */
970 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
971 {
972 DWORD ret;
973
974 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen);
975 if (!dwOutBufLen)
976 ret = ERROR_INVALID_PARAMETER;
977 else {
978 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
979 ULONG size;
980 TRACE("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces);
981 size = sizeof(IP_INTERFACE_INFO) + (numNonLoopbackInterfaces) *
982 sizeof(IP_ADAPTER_INDEX_MAP);
983
984 if (!pIfTable || *dwOutBufLen < size) {
985 *dwOutBufLen = size;
986 ret = ERROR_INSUFFICIENT_BUFFER;
987 }
988 else {
989 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
990
991 if (table) {
992 TRACE("table->numIndexes == 0x%x\n", table->numIndexes);
993 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes) *
994 sizeof(IP_ADAPTER_INDEX_MAP);
995 if (*dwOutBufLen < size) {
996 *dwOutBufLen = size;
997 ret = ERROR_INSUFFICIENT_BUFFER;
998 }
999 else {
1000 DWORD ndx;
1001
1002 pIfTable->NumAdapters = 0;
1003 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1004 const char *walker, *name;
1005 WCHAR *assigner;
1006
1007 pIfTable->Adapter[ndx].Index = table->indexes[ndx];
1008 name = getInterfaceNameByIndex(table->indexes[ndx]);
1009 for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
1010 walker && *walker &&
1011 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
1012 walker++, assigner++)
1013 *assigner = *walker;
1014 *assigner = 0;
1015 consumeInterfaceName(name);
1016 pIfTable->NumAdapters++;
1017 }
1018 ret = NO_ERROR;
1019 }
1020 free(table);
1021 }
1022 else
1023 ret = ERROR_OUTOFMEMORY;
1024 }
1025 }
1026 TRACE("returning %ld\n", ret);
1027 return ret;
1028 }
1029
1030
1031 static int IpAddrTableSorter(const void *a, const void *b)
1032 {
1033 int ret;
1034
1035 if (a && b)
1036 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr;
1037 else
1038 ret = 0;
1039 return ret;
1040 }
1041
1042
1043 /******************************************************************
1044 * GetIpAddrTable (IPHLPAPI.@)
1045 *
1046 *
1047 * PARAMS
1048 *
1049 * pIpAddrTable [In/Out]
1050 * pdwSize [In/Out]
1051 * bOrder [In]
1052 *
1053 * RETURNS
1054 *
1055 * DWORD
1056 *
1057 */
1058 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
1059 {
1060 DWORD ret;
1061
1062 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize,
1063 (DWORD)bOrder);
1064 if (!pdwSize)
1065 ret = ERROR_INVALID_PARAMETER;
1066 else {
1067 DWORD numInterfaces = getNumInterfaces();
1068 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) *
1069 sizeof(MIB_IPADDRROW);
1070
1071 if (!pIpAddrTable || *pdwSize < size) {
1072 *pdwSize = size;
1073 ret = ERROR_INSUFFICIENT_BUFFER;
1074 }
1075 else {
1076 InterfaceIndexTable *table = getInterfaceIndexTable();
1077
1078 if (table) {
1079 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) *
1080 sizeof(MIB_IPADDRROW);
1081 if (*pdwSize < size) {
1082 *pdwSize = size;
1083 ret = ERROR_INSUFFICIENT_BUFFER;
1084 }
1085 else {
1086 DWORD ndx, bcast;
1087
1088 pIpAddrTable->dwNumEntries = 0;
1089 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1090 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx];
1091 pIpAddrTable->table[ndx].dwAddr =
1092 getInterfaceIPAddrByIndex(table->indexes[ndx]);
1093 pIpAddrTable->table[ndx].dwMask =
1094 getInterfaceMaskByIndex(table->indexes[ndx]);
1095 /* the dwBCastAddr member isn't the broadcast address, it indicates
1096 * whether the interface uses the 1's broadcast address (1) or the
1097 * 0's broadcast address (0).
1098 */
1099 bcast = getInterfaceBCastAddrByIndex(table->indexes[ndx]);
1100 pIpAddrTable->table[ndx].dwBCastAddr =
1101 (bcast & pIpAddrTable->table[ndx].dwMask) ? 1 : 0;
1102 /* FIXME: hardcoded reasm size, not sure where to get it */
1103 pIpAddrTable->table[ndx].dwReasmSize = 65535;
1104 pIpAddrTable->table[ndx].unused1 = 0;
1105 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */
1106 pIpAddrTable->dwNumEntries++;
1107 }
1108 if (bOrder)
1109 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries,
1110 sizeof(MIB_IPADDRROW), IpAddrTableSorter);
1111 ret = NO_ERROR;
1112 }
1113 free(table);
1114 }
1115 else
1116 ret = ERROR_OUTOFMEMORY;
1117 }
1118 }
1119 TRACE("returning %ld\n", ret);
1120 return ret;
1121 }
1122
1123
1124 static int IpForwardTableSorter(const void *a, const void *b)
1125 {
1126 int ret;
1127
1128 if (a && b) {
1129 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b;
1130
1131 ret = rowA->dwForwardDest - rowB->dwForwardDest;
1132 if (ret == 0) {
1133 ret = rowA->dwForwardProto - rowB->dwForwardProto;
1134 if (ret == 0) {
1135 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy;
1136 if (ret == 0)
1137 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop;
1138 }
1139 }
1140 }
1141 else
1142 ret = 0;
1143 return ret;
1144 }
1145
1146
1147 /******************************************************************
1148 * GetIpForwardTable (IPHLPAPI.@)
1149 *
1150 *
1151 * PARAMS
1152 *
1153 * pIpForwardTable [In/Out]
1154 * pdwSize [In/Out]
1155 * bOrder [In]
1156 *
1157 * RETURNS
1158 *
1159 * DWORD
1160 *
1161 */
1162 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
1163 {
1164 DWORD ret;
1165
1166 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable,
1167 pdwSize, (DWORD)bOrder);
1168 if (!pdwSize)
1169 ret = ERROR_INVALID_PARAMETER;
1170 else {
1171 DWORD numRoutes = getNumRoutes();
1172 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) *
1173 sizeof(MIB_IPFORWARDROW);
1174
1175 if (!pIpForwardTable || *pdwSize < sizeNeeded) {
1176 *pdwSize = sizeNeeded;
1177 ret = ERROR_INSUFFICIENT_BUFFER;
1178 }
1179 else {
1180 RouteTable *table = getRouteTable();
1181 if (table) {
1182 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) *
1183 sizeof(MIB_IPFORWARDROW);
1184 if (*pdwSize < sizeNeeded) {
1185 *pdwSize = sizeNeeded;
1186 ret = ERROR_INSUFFICIENT_BUFFER;
1187 }
1188 else {
1189 DWORD ndx;
1190
1191 pIpForwardTable->dwNumEntries = table->numRoutes;
1192 for (ndx = 0; ndx < numRoutes; ndx++) {
1193 pIpForwardTable->table[ndx].dwForwardIfIndex =
1194 table->routes[ndx].ifIndex + 1;
1195 pIpForwardTable->table[ndx].dwForwardDest =
1196 table->routes[ndx].dest;
1197 pIpForwardTable->table[ndx].dwForwardMask =
1198 table->routes[ndx].mask;
1199 pIpForwardTable->table[ndx].dwForwardPolicy = 0;
1200 pIpForwardTable->table[ndx].dwForwardNextHop =
1201 table->routes[ndx].gateway;
1202 /* FIXME: this type is appropriate for local interfaces; may not
1203 always be appropriate */
1204 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
1205 /* FIXME: other protos might be appropriate, e.g. the default route
1206 is typically set with MIB_IPPROTO_NETMGMT instead */
1207 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL;
1208 /* punt on age and AS */
1209 pIpForwardTable->table[ndx].dwForwardAge = 0;
1210 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0;
1211 pIpForwardTable->table[ndx].dwForwardMetric1 =
1212 table->routes[ndx].metric;
1213 /* rest of the metrics are 0.. */
1214 pIpForwardTable->table[ndx].dwForwardMetric2 = 0;
1215 pIpForwardTable->table[ndx].dwForwardMetric3 = 0;
1216 pIpForwardTable->table[ndx].dwForwardMetric4 = 0;
1217 pIpForwardTable->table[ndx].dwForwardMetric5 = 0;
1218 }
1219 if (bOrder)
1220 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
1221 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
1222 ret = NO_ERROR;
1223 }
1224 HeapFree(GetProcessHeap(), 0, table);
1225 }
1226 else
1227 ret = ERROR_OUTOFMEMORY;
1228 }
1229 }
1230 TRACE("returning %ld\n", ret);
1231 return ret;
1232 }
1233
1234
1235 static int IpNetTableSorter(const void *a, const void *b)
1236 {
1237 int ret;
1238
1239 if (a && b)
1240 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr;
1241 else
1242 ret = 0;
1243 return ret;
1244 }
1245
1246
1247 /******************************************************************
1248 * GetIpNetTable (IPHLPAPI.@)
1249 *
1250 *
1251 * PARAMS
1252 *
1253 * pIpNetTable [In/Out]
1254 * pdwSize [In/Out]
1255 * bOrder [In]
1256 *
1257 * RETURNS
1258 *
1259 * DWORD
1260 *
1261 */
1262 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
1263 {
1264 DWORD ret = NO_ERROR;
1265
1266 TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize,
1267 (DWORD)bOrder);
1268 if (!pdwSize)
1269 ret = ERROR_INVALID_PARAMETER;
1270 else {
1271 DWORD numEntries = getNumArpEntries();
1272 ULONG size = sizeof(MIB_IPNETTABLE);
1273
1274 if (numEntries > 1)
1275 size += (numEntries - 1) * sizeof(MIB_IPNETROW);
1276 if (!pIpNetTable || *pdwSize < size) {
1277 *pdwSize = size;
1278 ret = ERROR_INSUFFICIENT_BUFFER;
1279 }
1280 else {
1281 PMIB_IPNETTABLE table = getArpTable();
1282 if (table) {
1283 size = sizeof(MIB_IPNETTABLE);
1284 if (table->dwNumEntries > 1)
1285 size += (table->dwNumEntries - 1) * sizeof(MIB_IPNETROW);
1286 if (*pdwSize < size) {
1287 *pdwSize = size;
1288 ret = ERROR_INSUFFICIENT_BUFFER;
1289 }
1290 else {
1291 *pdwSize = size;
1292 memcpy(pIpNetTable, table, size);
1293 if (bOrder)
1294 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries,
1295 sizeof(MIB_IPNETROW), IpNetTableSorter);
1296 ret = NO_ERROR;
1297 }
1298 HeapFree(GetProcessHeap(), 0, table);
1299 }
1300 }
1301 }
1302 TRACE("returning %d\n", ret);
1303 return ret;
1304 }
1305
1306
1307 /******************************************************************
1308 * GetIpStatistics (IPHLPAPI.@)
1309 *
1310 *
1311 * PARAMS
1312 *
1313 * pStats [In/Out]
1314 *
1315 * RETURNS
1316 *
1317 * DWORD
1318 *
1319 */
1320 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
1321 {
1322 return GetIpStatisticsEx(pStats, PF_INET);
1323 }
1324
1325 /******************************************************************
1326 * GetIpStatisticsEx (IPHLPAPI.@)
1327 *
1328 *
1329 * PARAMS
1330 *
1331 * pStats [In/Out]
1332 * dwFamily [In]
1333 *
1334 * RETURNS
1335 *
1336 * DWORD
1337 *
1338 */
1339 DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
1340 {
1341 DWORD ret;
1342
1343 TRACE("pStats %p\n", pStats);
1344 ret = getIPStats(pStats, dwFamily);
1345 TRACE("returning %ld\n", ret);
1346 return ret;
1347 }
1348
1349 /******************************************************************
1350 * GetNetworkParams (IPHLPAPI.@)
1351 *
1352 *
1353 * PARAMS
1354 *
1355 * pFixedInfo [In/Out]
1356 * pOutBufLen [In/Out]
1357 *
1358 * RETURNS
1359 *
1360 * DWORD
1361 *
1362 */
1363 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
1364 {
1365 DWORD ret, size;
1366 LONG regReturn;
1367 HKEY hKey;
1368 PIPHLP_RES_INFO resInfo;
1369
1370 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen);
1371 if (!pOutBufLen)
1372 return ERROR_INVALID_PARAMETER;
1373
1374 resInfo = getResInfo();
1375 if (!resInfo)
1376 return ERROR_OUTOFMEMORY;
1377
1378 size = sizeof(FIXED_INFO) + (resInfo->riCount > 1 ? (resInfo->riCount-1) *
1379 sizeof(IP_ADDR_STRING) : 0);
1380 if (!pFixedInfo || *pOutBufLen < size) {
1381 *pOutBufLen = size;
1382 disposeResInfo( resInfo );
1383 return ERROR_BUFFER_OVERFLOW;
1384 }
1385
1386 memset(pFixedInfo, 0, size);
1387 size = sizeof(pFixedInfo->HostName);
1388 GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
1389 size = sizeof(pFixedInfo->DomainName);
1390 GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
1391
1392 TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName);
1393
1394 if (resInfo->riCount > 0)
1395 {
1396 CopyMemory(&pFixedInfo->DnsServerList, resInfo->DnsList, sizeof(IP_ADDR_STRING));
1397 if (resInfo->riCount > 1)
1398 {
1399 IP_ADDR_STRING *pSrc = resInfo->DnsList->Next;
1400 IP_ADDR_STRING *pTarget = (struct _IP_ADDR_STRING*)((char*)pFixedInfo + sizeof(FIXED_INFO));
1401
1402 pFixedInfo->DnsServerList.Next = pTarget;
1403
1404 do
1405 {
1406 CopyMemory(pTarget, pSrc, sizeof(IP_ADDR_STRING));
1407 resInfo->riCount--;
1408 if (resInfo->riCount > 1)
1409 {
1410 pTarget->Next = (IP_ADDR_STRING*)((char*)pTarget + sizeof(IP_ADDR_STRING));
1411 pTarget = pTarget->Next;
1412 pSrc = pSrc->Next;
1413 }
1414 else
1415 {
1416 pTarget->Next = NULL;
1417 break;
1418 }
1419 }
1420 while(TRUE);
1421 }
1422 else
1423 {
1424 pFixedInfo->DnsServerList.Next = NULL;
1425 }
1426 }
1427
1428 pFixedInfo->NodeType = HYBRID_NODETYPE;
1429 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1430 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey);
1431 if (regReturn != ERROR_SUCCESS)
1432 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1433 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ,
1434 &hKey);
1435 if (regReturn == ERROR_SUCCESS)
1436 {
1437 DWORD size = sizeof(pFixedInfo->ScopeId);
1438
1439 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (PBYTE)pFixedInfo->ScopeId, &size);
1440 RegCloseKey(hKey);
1441 }
1442
1443 disposeResInfo( resInfo );
1444 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
1445 I suppose could also check for a listener on port 53 to set EnableDns */
1446 ret = NO_ERROR;
1447 TRACE("returning %ld\n", ret);
1448
1449 return ret;
1450 }
1451
1452
1453 /******************************************************************
1454 * GetNumberOfInterfaces (IPHLPAPI.@)
1455 *
1456 *
1457 * PARAMS
1458 *
1459 * pdwNumIf [In/Out]
1460 *
1461 * RETURNS
1462 *
1463 * DWORD
1464 *
1465 */
1466 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
1467 {
1468 DWORD ret;
1469
1470 TRACE("pdwNumIf %p\n", pdwNumIf);
1471 if (!pdwNumIf)
1472 ret = ERROR_INVALID_PARAMETER;
1473 else {
1474 *pdwNumIf = getNumInterfaces();
1475 ret = NO_ERROR;
1476 }
1477 TRACE("returning %ld\n", ret);
1478 return ret;
1479 }
1480
1481
1482 /******************************************************************
1483 * GetPerAdapterInfo (IPHLPAPI.@)
1484 *
1485 *
1486 * PARAMS
1487 *
1488 * IfIndex [In]
1489 * pPerAdapterInfo [In/Out]
1490 * pOutBufLen [In/Out]
1491 *
1492 * RETURNS
1493 *
1494 * DWORD
1495 *
1496 */
1497 static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, PVOID Data)
1498 {
1499 IP_ADDR_STRING *pNext;
1500 PNAME_SERVER_LIST_CONTEXT Context = (PNAME_SERVER_LIST_CONTEXT)Data;
1501
1502 if (!Context->NumServers)
1503 {
1504 if (Context->uSizeAvailable >= Context->uSizeRequired)
1505 {
1506 WideCharToMultiByte(CP_ACP, 0, Server, -1, Context->pData->DnsServerList.IpAddress.String, 16, NULL, NULL);
1507 Context->pData->DnsServerList.IpAddress.String[15] = '\0';
1508 Context->pLastAddr = &Context->pData->DnsServerList;
1509 }
1510 }
1511 else
1512 {
1513 Context->uSizeRequired += sizeof(IP_ADDR_STRING);
1514 if (Context->uSizeAvailable >= Context->uSizeRequired)
1515 {
1516 pNext = (IP_ADDR_STRING*)(((char*)Context->pLastAddr) + sizeof(IP_ADDR_STRING));
1517 WideCharToMultiByte(CP_ACP, 0, Server, -1, pNext->IpAddress.String, 16, NULL, NULL);
1518 pNext->IpAddress.String[15] = '\0';
1519 Context->pLastAddr->Next = pNext;
1520 Context->pLastAddr = pNext;
1521 pNext->Next = NULL;
1522 }
1523 }
1524 Context->NumServers++;
1525 }
1526
1527 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
1528 {
1529 HKEY hkey;
1530 DWORD dwSize = 0;
1531 const char *ifName;
1532 NAME_SERVER_LIST_CONTEXT Context;
1533 WCHAR keyname[200] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
1534
1535 if (!pOutBufLen)
1536 return ERROR_INVALID_PARAMETER;
1537
1538 if (!pPerAdapterInfo || *pOutBufLen < sizeof(IP_PER_ADAPTER_INFO))
1539 {
1540 *pOutBufLen = sizeof(IP_PER_ADAPTER_INFO);
1541 return ERROR_BUFFER_OVERFLOW;
1542 }
1543
1544 ifName = getInterfaceNameByIndex(IfIndex);
1545 if (!ifName)
1546 return ERROR_INVALID_PARAMETER;
1547
1548 MultiByteToWideChar(CP_ACP, 0, ifName, -1, &keyname[62], sizeof(keyname)/sizeof(WCHAR) - 63);
1549 HeapFree(GetProcessHeap(), 0, (LPVOID)ifName);
1550
1551 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey) != ERROR_SUCCESS)
1552 {
1553 return ERROR_NOT_SUPPORTED;
1554 }
1555 Context.NumServers = 0;
1556 Context.uSizeAvailable = *pOutBufLen;
1557 Context.uSizeRequired = sizeof(IP_PER_ADAPTER_INFO);
1558 Context.pData = pPerAdapterInfo;
1559
1560 if (*pOutBufLen >= sizeof(IP_PER_ADAPTER_INFO))
1561 ZeroMemory(pPerAdapterInfo, sizeof(IP_PER_ADAPTER_INFO));
1562
1563 EnumNameServers(hkey, &keyname[62], &Context, CreateNameServerListEnumNamesFunc);
1564
1565 if (Context.uSizeRequired > Context.uSizeAvailable)
1566 {
1567 *pOutBufLen = Context.uSizeRequired;
1568 RegCloseKey(hkey);
1569 return ERROR_BUFFER_OVERFLOW;
1570 }
1571
1572 if(RegQueryValueExW(hkey, L"DHCPNameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
1573 {
1574 pPerAdapterInfo->AutoconfigActive = TRUE;
1575 }
1576
1577 RegCloseKey(hkey);
1578 return NOERROR;
1579 }
1580
1581
1582 /******************************************************************
1583 * GetRTTAndHopCount (IPHLPAPI.@)
1584 *
1585 *
1586 * PARAMS
1587 *
1588 * DestIpAddress [In]
1589 * HopCount [In/Out]
1590 * MaxHops [In]
1591 * RTT [In/Out]
1592 *
1593 * RETURNS
1594 *
1595 * BOOL
1596 *
1597 */
1598 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
1599 {
1600 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
1601 DestIpAddress, HopCount, MaxHops, RTT);
1602 FIXME(":stub\n");
1603 return (BOOL) 0;
1604 }
1605
1606
1607 /******************************************************************
1608 * GetTcpStatisticsEx (IPHLPAPI.@)
1609 *
1610 *
1611 * PARAMS
1612 *
1613 * pStats [In/Out]
1614 * dwFamily [In]
1615 *
1616 * RETURNS
1617 *
1618 * DWORD
1619 *
1620 */
1621 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
1622 {
1623 DWORD ret;
1624
1625 TRACE("pStats %p\n", pStats);
1626 ret = getTCPStats(pStats, dwFamily);
1627 TRACE("returning %ld\n", ret);
1628 return ret;
1629 }
1630
1631 /******************************************************************
1632 * GetTcpStatistics (IPHLPAPI.@)
1633 *
1634 *
1635 * PARAMS
1636 *
1637 * pStats [In/Out]
1638 *
1639 * RETURNS
1640 *
1641 * DWORD
1642 *
1643 */
1644 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
1645 {
1646 return GetTcpStatisticsEx(pStats, PF_INET);
1647 }
1648
1649
1650 static int TcpTableSorter(const void *a, const void *b)
1651 {
1652 int ret;
1653
1654 if (a && b) {
1655 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
1656
1657 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1658 if (ret == 0) {
1659 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1660 if (ret == 0) {
1661 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
1662 if (ret == 0)
1663 ret = rowA->dwRemotePort - rowB->dwRemotePort;
1664 }
1665 }
1666 }
1667 else
1668 ret = 0;
1669 return ret;
1670 }
1671
1672
1673 /******************************************************************
1674 * GetTcpTable (IPHLPAPI.@)
1675 *
1676 * Get the table of active TCP connections.
1677 *
1678 * PARAMS
1679 * pTcpTable [Out] buffer for TCP connections table
1680 * pdwSize [In/Out] length of output buffer
1681 * bOrder [In] whether to order the table
1682 *
1683 * RETURNS
1684 * Success: NO_ERROR
1685 * Failure: error code from winerror.h
1686 *
1687 * NOTES
1688 * If pdwSize is less than required, the function will return
1689 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to
1690 * the required byte size.
1691 * If bOrder is true, the returned table will be sorted, first by
1692 * local address and port number, then by remote address and port
1693 * number.
1694 */
1695 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
1696 {
1697 DWORD ret = NO_ERROR;
1698
1699 TRACE("pTcpTable %p, pdwSize %p, bOrder %d\n", pTcpTable, pdwSize,
1700 (DWORD)bOrder);
1701 if (!pdwSize)
1702 ret = ERROR_INVALID_PARAMETER;
1703 else {
1704 DWORD numEntries = getNumTcpEntries();
1705 DWORD size = sizeof(MIB_TCPTABLE);
1706
1707 if (numEntries > 1)
1708 size += (numEntries - 1) * sizeof(MIB_TCPROW);
1709 if (!pTcpTable || *pdwSize < size) {
1710 *pdwSize = size;
1711 ret = ERROR_INSUFFICIENT_BUFFER;
1712 }
1713 else {
1714 PMIB_TCPTABLE pTcpTable = getTcpTable();
1715 if (pTcpTable)
1716 {
1717 size = sizeof(MIB_TCPTABLE);
1718 if (pTcpTable->dwNumEntries > 1)
1719 size += (pTcpTable->dwNumEntries - 1) * sizeof(MIB_TCPROW);
1720 *pdwSize = size;
1721
1722 if (bOrder)
1723 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1724 sizeof(MIB_TCPROW), TcpTableSorter);
1725 ret = NO_ERROR;
1726 }
1727 }
1728 }
1729 TRACE("returning %d\n", ret);
1730 return ret;
1731 }
1732
1733
1734 /******************************************************************
1735 * GetUdpStatisticsEx (IPHLPAPI.@)
1736 *
1737 *
1738 * PARAMS
1739 *
1740 * pStats [In/Out]
1741 * dwFamily [In]
1742 *
1743 * RETURNS
1744 *
1745 * DWORD
1746 *
1747 */
1748 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
1749 {
1750 DWORD ret;
1751
1752 TRACE("pStats %p\n", pStats);
1753 ret = getUDPStats(pStats, dwFamily);
1754 TRACE("returning %ld\n", ret);
1755 return ret;
1756 }
1757
1758 /******************************************************************
1759 * GetUdpStatistics (IPHLPAPI.@)
1760 *
1761 *
1762 * PARAMS
1763 *
1764 * pStats [In/Out]
1765 *
1766 * RETURNS
1767 *
1768 * DWORD
1769 *
1770 */
1771 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1772 {
1773 return GetUdpStatisticsEx(pStats, PF_INET);
1774 }
1775
1776
1777 static int UdpTableSorter(const void *a, const void *b)
1778 {
1779 int ret;
1780
1781 if (a && b) {
1782 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1783
1784 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1785 if (ret == 0)
1786 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1787 }
1788 else
1789 ret = 0;
1790 return ret;
1791 }
1792
1793
1794 /******************************************************************
1795 * GetUdpTable (IPHLPAPI.@)
1796 *
1797 *
1798 * PARAMS
1799 *
1800 * pUdpTable [In/Out]
1801 * pdwSize [In/Out]
1802 * bOrder [In]
1803 *
1804 * RETURNS
1805 *
1806 * DWORD
1807 *
1808 */
1809 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1810 {
1811 DWORD ret;
1812
1813 TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
1814 (DWORD)bOrder);
1815 if (!pdwSize)
1816 ret = ERROR_INVALID_PARAMETER;
1817 else {
1818 DWORD numEntries = getNumUdpEntries();
1819 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1820
1821 if (!pUdpTable || *pdwSize < size) {
1822 *pdwSize = size;
1823 ret = ERROR_INSUFFICIENT_BUFFER;
1824 }
1825 else {
1826 PMIB_UDPTABLE table = getUdpTable();
1827
1828 if (table) {
1829 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1830 sizeof(MIB_UDPROW);
1831 if (*pdwSize < size) {
1832 *pdwSize = size;
1833 ret = ERROR_INSUFFICIENT_BUFFER;
1834 }
1835 else {
1836 memcpy(pUdpTable, table, size);
1837 if (bOrder)
1838 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1839 sizeof(MIB_UDPROW), UdpTableSorter);
1840 ret = NO_ERROR;
1841 }
1842 free(table);
1843 }
1844 else
1845 ret = ERROR_OUTOFMEMORY;
1846 }
1847 }
1848 TRACE("returning %ld\n", ret);
1849 return ret;
1850 }
1851
1852
1853 /******************************************************************
1854 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1855 *
1856 * This is a Win98-only function to get information on "unidirectional"
1857 * adapters. Since this is pretty nonsensical in other contexts, it
1858 * never returns anything.
1859 *
1860 * PARAMS
1861 * pIPIfInfo [Out] buffer for adapter infos
1862 * dwOutBufLen [Out] length of the output buffer
1863 *
1864 * RETURNS
1865 * Success: NO_ERROR
1866 * Failure: error code from winerror.h
1867 *
1868 * FIXME
1869 * Stub, returns ERROR_NOT_SUPPORTED.
1870 */
1871 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1872 {
1873 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
1874 /* a unidirectional adapter?? not bloody likely! */
1875 return ERROR_NOT_SUPPORTED;
1876 }
1877
1878
1879 /******************************************************************
1880 * IpReleaseAddress (IPHLPAPI.@)
1881 *
1882 * Release an IP obtained through DHCP,
1883 *
1884 * PARAMS
1885 * AdapterInfo [In] adapter to release IP address
1886 *
1887 * RETURNS
1888 * Success: NO_ERROR
1889 * Failure: error code from winerror.h
1890 *
1891 */
1892 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1893 {
1894 COMM_DHCP_REPLY Reply;
1895 COMM_DHCP_REQ Request;
1896 DWORD BytesRead;
1897
1898 Request.AdapterIndex = AdapterInfo->Index;
1899 Request.Type = DhcpReqReleaseIpAddress;
1900
1901 TRACE("AdapterInfo %p\n", AdapterInfo);
1902
1903 if (CallNamedPipe(DHCP_PIPE_NAME,
1904 &Request,
1905 sizeof(Request),
1906 &Reply,
1907 sizeof(Reply),
1908 &BytesRead,
1909 NMPWAIT_USE_DEFAULT_WAIT))
1910 {
1911 if (Reply.Reply)
1912 return NO_ERROR;
1913
1914 return ERROR_INVALID_PARAMETER;
1915 }
1916
1917 return ERROR_PROC_NOT_FOUND;
1918 }
1919
1920
1921 /******************************************************************
1922 * IpRenewAddress (IPHLPAPI.@)
1923 *
1924 * Renew an IP obtained through DHCP.
1925 *
1926 * PARAMS
1927 * AdapterInfo [In] adapter to renew IP address
1928 *
1929 * RETURNS
1930 * Success: NO_ERROR
1931 * Failure: error code from winerror.h
1932 */
1933 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1934 {
1935 COMM_DHCP_REPLY Reply;
1936 COMM_DHCP_REQ Request;
1937 DWORD BytesRead;
1938
1939 Request.AdapterIndex = AdapterInfo->Index;
1940 Request.Type = DhcpReqRenewIpAddress;
1941
1942 TRACE("AdapterInfo %p\n", AdapterInfo);
1943
1944 if (CallNamedPipe(DHCP_PIPE_NAME,
1945 &Request,
1946 sizeof(Request),
1947 &Reply,
1948 sizeof(Reply),
1949 &BytesRead,
1950 NMPWAIT_USE_DEFAULT_WAIT))
1951 {
1952 if (Reply.Reply)
1953 return NO_ERROR;
1954
1955 return ERROR_INVALID_PARAMETER;
1956 }
1957
1958 return ERROR_PROC_NOT_FOUND;
1959 }
1960
1961
1962 /******************************************************************
1963 * NotifyAddrChange (IPHLPAPI.@)
1964 *
1965 * Notify caller whenever the ip-interface map is changed.
1966 *
1967 * PARAMS
1968 * Handle [Out] handle usable in asynchronous notification
1969 * overlapped [In] overlapped structure that notifies the caller
1970 *
1971 * RETURNS
1972 * Success: NO_ERROR
1973 * Failure: error code from winerror.h
1974 *
1975 * FIXME
1976 * Stub, returns ERROR_NOT_SUPPORTED.
1977 */
1978 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1979 {
1980 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
1981 return ERROR_NOT_SUPPORTED;
1982 }
1983
1984
1985 /******************************************************************
1986 * NotifyRouteChange (IPHLPAPI.@)
1987 *
1988 * Notify caller whenever the ip routing table is changed.
1989 *
1990 * PARAMS
1991 * Handle [Out] handle usable in asynchronous notification
1992 * overlapped [In] overlapped structure that notifies the caller
1993 *
1994 * RETURNS
1995 * Success: NO_ERROR
1996 * Failure: error code from winerror.h
1997 *
1998 * FIXME
1999 * Stub, returns ERROR_NOT_SUPPORTED.
2000 */
2001 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2002 {
2003 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2004 return ERROR_NOT_SUPPORTED;
2005 }
2006
2007
2008 /******************************************************************
2009 * SendARP (IPHLPAPI.@)
2010 *
2011 * Send an ARP request.
2012 *
2013 * PARAMS
2014 * DestIP [In] attempt to obtain this IP
2015 * SrcIP [In] optional sender IP address
2016 * pMacAddr [Out] buffer for the mac address
2017 * PhyAddrLen [In/Out] length of the output buffer
2018 *
2019 * RETURNS
2020 * Success: NO_ERROR
2021 * Failure: error code from winerror.h
2022 *
2023 * FIXME
2024 * Stub, returns ERROR_NOT_SUPPORTED.
2025 */
2026 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
2027 {
2028 FIXME("(DestIP 0x%08x, SrcIP 0x%08x, pMacAddr %p, PhyAddrLen %p): stub\n",
2029 DestIP, SrcIP, pMacAddr, PhyAddrLen);
2030 return ERROR_NOT_SUPPORTED;
2031 }
2032
2033
2034 /******************************************************************
2035 * SetIfEntry (IPHLPAPI.@)
2036 *
2037 * Set the administrative status of an interface.
2038 *
2039 * PARAMS
2040 * pIfRow [In] dwAdminStatus member specifies the new status.
2041 *
2042 * RETURNS
2043 * Success: NO_ERROR
2044 * Failure: error code from winerror.h
2045 *
2046 * FIXME
2047 * Stub, returns ERROR_NOT_SUPPORTED.
2048 */
2049 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
2050 {
2051 FIXME("(pIfRow %p): stub\n", pIfRow);
2052 /* this is supposed to set an interface administratively up or down.
2053 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
2054 this sort of down is indistinguishable from other sorts of down (e.g. no
2055 link). */
2056 return ERROR_NOT_SUPPORTED;
2057 }
2058
2059
2060 /******************************************************************
2061 * SetIpForwardEntry (IPHLPAPI.@)
2062 *
2063 * Modify an existing route.
2064 *
2065 * PARAMS
2066 * pRoute [In] route with the new information
2067 *
2068 * RETURNS
2069 * Success: NO_ERROR
2070 * Failure: error code from winerror.h
2071 *
2072 */
2073 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
2074 {
2075 return setIpForwardEntry( pRoute );
2076 }
2077
2078
2079 /******************************************************************
2080 * SetIpNetEntry (IPHLPAPI.@)
2081 *
2082 * Modify an existing ARP entry.
2083 *
2084 * PARAMS
2085 * pArpEntry [In] ARP entry with the new information
2086 *
2087 * RETURNS
2088 * Success: NO_ERROR
2089 * Failure: error code from winerror.h
2090 */
2091 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
2092 {
2093 HANDLE tcpFile;
2094 NTSTATUS status;
2095 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req =
2096 TCP_REQUEST_SET_INFORMATION_INIT;
2097 TDIEntityID id;
2098 DWORD returnSize;
2099 PMIB_IPNETROW arpBuff;
2100
2101 if (!pArpEntry)
2102 return ERROR_INVALID_PARAMETER;
2103
2104 if (!NT_SUCCESS(openTcpFile( &tcpFile )))
2105 return ERROR_NOT_SUPPORTED;
2106
2107 if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id )))
2108 {
2109 closeTcpFile(tcpFile);
2110 return ERROR_INVALID_PARAMETER;
2111 }
2112
2113 req.Req.ID.toi_class = INFO_CLASS_PROTOCOL;
2114 req.Req.ID.toi_type = INFO_TYPE_PROVIDER;
2115 req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID;
2116 req.Req.ID.toi_entity.tei_instance = id.tei_instance;
2117 req.Req.ID.toi_entity.tei_entity = AT_ENTITY;
2118 req.Req.BufferSize = sizeof(MIB_IPNETROW);
2119 arpBuff = (PMIB_IPNETROW)&req.Req.Buffer[0];
2120
2121 RtlCopyMemory(arpBuff, pArpEntry, sizeof(MIB_IPNETROW));
2122
2123 status = DeviceIoControl( tcpFile,
2124 IOCTL_TCP_SET_INFORMATION_EX,
2125 &req,
2126 sizeof(req),
2127 NULL,
2128 0,
2129 &returnSize,
2130 NULL );
2131
2132 closeTcpFile(tcpFile);
2133
2134 if (status)
2135 return NO_ERROR;
2136 else
2137 return ERROR_INVALID_PARAMETER;
2138 }
2139
2140
2141 /******************************************************************
2142 * SetIpStatistics (IPHLPAPI.@)
2143 *
2144 * Toggle IP forwarding and det the default TTL value.
2145 *
2146 * PARAMS
2147 * pIpStats [In] IP statistics with the new information
2148 *
2149 * RETURNS
2150 * Success: NO_ERROR
2151 * Failure: error code from winerror.h
2152 *
2153 * FIXME
2154 * Stub, returns NO_ERROR.
2155 */
2156 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
2157 {
2158 FIXME("(pIpStats %p): stub\n", pIpStats);
2159 return 0;
2160 }
2161
2162
2163 /******************************************************************
2164 * SetIpTTL (IPHLPAPI.@)
2165 *
2166 * Set the default TTL value.
2167 *
2168 * PARAMS
2169 * nTTL [In] new TTL value
2170 *
2171 * RETURNS
2172 * Success: NO_ERROR
2173 * Failure: error code from winerror.h
2174 *
2175 * FIXME
2176 * Stub, returns NO_ERROR.
2177 */
2178 DWORD WINAPI SetIpTTL(UINT nTTL)
2179 {
2180 FIXME("(nTTL %d): stub\n", nTTL);
2181 return 0;
2182 }
2183
2184
2185 /******************************************************************
2186 * SetTcpEntry (IPHLPAPI.@)
2187 *
2188 * Set the state of a TCP connection.
2189 *
2190 * PARAMS
2191 * pTcpRow [In] specifies connection with new state
2192 *
2193 * RETURNS
2194 * Success: NO_ERROR
2195 * Failure: error code from winerror.h
2196 *
2197 * FIXME
2198 * Stub, returns NO_ERROR.
2199 */
2200 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
2201 {
2202 FIXME("(pTcpRow %p): stub\n", pTcpRow);
2203 return 0;
2204 }
2205
2206
2207 /******************************************************************
2208 * UnenableRouter (IPHLPAPI.@)
2209 *
2210 * Decrement the IP-forwarding reference count. Turn off IP-forwarding
2211 * if it reaches zero.
2212 *
2213 * PARAMS
2214 * pOverlapped [In/Out] should be the same as in EnableRouter()
2215 * lpdwEnableCount [Out] optional, receives reference count
2216 *
2217 * RETURNS
2218 * Success: NO_ERROR
2219 * Failure: error code from winerror.h
2220 *
2221 * FIXME
2222 * Stub, returns ERROR_NOT_SUPPORTED.
2223 */
2224 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
2225 {
2226 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped,
2227 lpdwEnableCount);
2228 return ERROR_NOT_SUPPORTED;
2229 }
2230
2231 /*
2232 * @unimplemented
2233 */
2234 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
2235 {
2236 FIXME(":stub\n");
2237 return 0L;
2238 }
2239
2240
2241 /*
2242 * @unimplemented
2243 */
2244 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
2245 {
2246 FIXME(":stub\n");
2247 return 0L;
2248 }
2249
2250 /*
2251 * @unimplemented
2252 */
2253 DWORD WINAPI GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
2254 {
2255 if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
2256 if (!pAdapterAddresses || *pOutBufLen == 0)
2257 return ERROR_BUFFER_OVERFLOW;
2258 if (Reserved) return ERROR_INVALID_PARAMETER;
2259
2260 FIXME(":stub\n");
2261 return ERROR_NO_DATA;
2262 }
2263
2264 /*
2265 * @unimplemented
2266 */
2267 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
2268 {
2269 FIXME(":stub\n");
2270 return 0L;
2271 }
2272
2273 /*
2274 * @unimplemented
2275 */
2276 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
2277 {
2278 FIXME(":stub\n");
2279 return 0L;
2280 }
2281
2282 /*
2283 * @unimplemented
2284 */
2285 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
2286 {
2287 FIXME(":stub\n");
2288 return 0L;
2289 }
2290
2291 /*
2292 * @unimplemented
2293 */
2294 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
2295 {
2296 FIXME(":stub\n");
2297 return 0L;
2298 }
2299
2300 /******************************************************************
2301 * GetIfTable2 (IPHLPAPI.@)
2302 *
2303 * PARAMS
2304 * pIfTable [In/Out]
2305 */
2306
2307 NETIOAPI_API WINAPI GetIfTable2(PMIB_IF_TABLE2 *pIfTable)
2308 {
2309 UNIMPLEMENTED;
2310 return ERROR_NOT_SUPPORTED;
2311 }
2312
2313 /******************************************************************
2314 * GetIfEntry2 (IPHLPAPI.@)
2315 *
2316 * PARAMS
2317 * pIfRow [In/Out]
2318 */
2319 NETIOAPI_API WINAPI GetIfEntry2(IN OUT PMIB_IF_ROW2 pIfRow)
2320 {
2321 TRACE("pIfRow %p\n", pIfRow);
2322 if (!pIfRow)
2323 return ERROR_INVALID_PARAMETER;
2324
2325 UNIMPLEMENTED;
2326 return ERROR_NOT_SUPPORTED;
2327 }
2328
2329 DWORD WINAPI
2330 SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute)
2331 {
2332 FIXME("SetIpForwardEntryToStack() stub\n");
2333 return 0L;
2334 }
2335
2336 DWORD WINAPI
2337 NhGetInterfaceNameFromDeviceGuid(DWORD dwUnknown1,
2338 DWORD dwUnknown2,
2339 DWORD dwUnknown3,
2340 DWORD dwUnknown4,
2341 DWORD dwUnknown5)
2342 {
2343 FIXME("NhGetInterfaceNameFromDeviceGuid() stub\n");
2344 return 0L;
2345 }