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