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