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