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