[IPHLPAPI] Implement the *_TABLE_OWNER_MODULE_* in GetExtendedTcp/UdpTable() 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 * AllocateAndGetTcpExTableFromStack (IPHLPAPI.@)
309 *
310 *
311 * PARAMS
312 *
313 * ppTcpTable [Out]
314 * bOrder [In] -- passed to GetExtendedTcpTable to order the table
315 * heap [In] -- heap from which the table is allocated
316 * flags [In] -- flags to HeapAlloc
317 * family [In] -- passed to GetExtendedTcpTable to select INET family
318 *
319 * RETURNS
320 *
321 * DWORD
322 *
323 */
324 DWORD WINAPI AllocateAndGetTcpExTableFromStack(PVOID *ppTcpTable,
325 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family)
326 {
327 DWORD ret;
328
329 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family 0x%08lx\n",
330 ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags, family);
331 if (!ppTcpTable)
332 ret = ERROR_INVALID_PARAMETER;
333 else {
334 DWORD dwSize = 0;
335
336 *ppTcpTable = NULL;
337 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0);
338 if (ret == ERROR_INSUFFICIENT_BUFFER) {
339 *ppTcpTable = (PMIB_TCPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize);
340 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0);
341 if (ret != NO_ERROR) {
342 HeapFree(heap, flags, *ppTcpTable);
343 *ppTcpTable = NULL;
344 }
345 }
346 }
347 TRACE("returning %ld\n", ret);
348 return ret;
349 }
350
351
352 /******************************************************************
353 * AllocateAndGetTcpExTable2FromStack (IPHLPAPI.@)
354 *
355 *
356 * PARAMS
357 *
358 * ppTcpTable [Out]
359 * bOrder [In] -- passed to GetExtendedTcpTable to order the table
360 * heap [In] -- heap from which the table is allocated
361 * flags [In] -- flags to HeapAlloc
362 * family [In] -- passed to GetExtendedTcpTable to select INET family
363 * class [In] -- passed to GetExtendedTcpTable to select information
364 *
365 * RETURNS
366 *
367 * DWORD
368 *
369 */
370 DWORD WINAPI AllocateAndGetTcpExTable2FromStack(PVOID *ppTcpTable,
371 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, TCP_TABLE_CLASS class)
372 {
373 DWORD ret;
374
375 TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family %ld, class %ld\n",
376 ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags, family, class);
377 if (!ppTcpTable)
378 ret = ERROR_INVALID_PARAMETER;
379 else {
380 DWORD dwSize = 0;
381
382 *ppTcpTable = NULL;
383 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0);
384 if (ret == ERROR_INSUFFICIENT_BUFFER) {
385 *ppTcpTable = HeapAlloc(heap, flags, dwSize);
386 ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0);
387 if (ret != NO_ERROR) {
388 HeapFree(heap, flags, *ppTcpTable);
389 *ppTcpTable = NULL;
390 }
391 }
392 }
393 TRACE("returning %ld\n", ret);
394 return ret;
395 }
396
397
398 /******************************************************************
399 * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
400 *
401 *
402 * PARAMS
403 *
404 * ppUdpTable [Out]
405 * bOrder [In] -- passed to GetUdpTable to order the table
406 * heap [In] -- heap from which the table is allocated
407 * flags [In] -- flags to HeapAlloc
408 *
409 * RETURNS
410 *
411 * DWORD
412 *
413 */
414 DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
415 BOOL bOrder, HANDLE heap, DWORD flags)
416 {
417 DWORD ret;
418
419 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
420 ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags);
421 if (!ppUdpTable)
422 ret = ERROR_INVALID_PARAMETER;
423 else {
424 DWORD dwSize = 0;
425
426 *ppUdpTable = NULL;
427 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
428 if (ret == ERROR_INSUFFICIENT_BUFFER) {
429 *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize);
430 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
431 if (ret != NO_ERROR) {
432 HeapFree(heap, flags, *ppUdpTable);
433 *ppUdpTable = NULL;
434 }
435 }
436 }
437 TRACE("returning %ld\n", ret);
438 return ret;
439 }
440
441
442 /******************************************************************
443 * AllocateAndGetUdpExTableFromStack (IPHLPAPI.@)
444 *
445 *
446 * PARAMS
447 *
448 * ppUdpTable [Out]
449 * bOrder [In] -- passed to GetExtendedUdpTable to order the table
450 * heap [In] -- heap from which the table is allocated
451 * flags [In] -- flags to HeapAlloc
452 * family [In] -- passed to GetExtendedUdpTable to select INET family
453 *
454 * RETURNS
455 *
456 * DWORD
457 *
458 */
459 DWORD WINAPI AllocateAndGetUdpExTableFromStack(PVOID *ppUdpTable,
460 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family)
461 {
462 DWORD ret;
463
464 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family 0x%08lx\n",
465 ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags, family);
466 if (!ppUdpTable)
467 ret = ERROR_INVALID_PARAMETER;
468 else {
469 DWORD dwSize = 0;
470
471 *ppUdpTable = NULL;
472 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0);
473 if (ret == ERROR_INSUFFICIENT_BUFFER) {
474 *ppUdpTable = (PMIB_UDPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize);
475 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0);
476 if (ret != NO_ERROR) {
477 HeapFree(heap, flags, *ppUdpTable);
478 *ppUdpTable = NULL;
479 }
480 }
481 }
482 TRACE("returning %ld\n", ret);
483 return ret;
484 }
485
486
487 /******************************************************************
488 * AllocateAndGetUdpExTable2FromStack (IPHLPAPI.@)
489 *
490 *
491 * PARAMS
492 *
493 * ppUdpTable [Out]
494 * bOrder [In] -- passed to GetExtendedUdpTable to order the table
495 * heap [In] -- heap from which the table is allocated
496 * flags [In] -- flags to HeapAlloc
497 * family [In] -- passed to GetExtendedUdpTable to select INET family
498 * class [In] -- passed to GetExtendedUdpTable to select information
499 *
500 * RETURNS
501 *
502 * DWORD
503 *
504 */
505 DWORD WINAPI AllocateAndGetUdpExTable2FromStack(PVOID *ppUdpTable,
506 BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, UDP_TABLE_CLASS class)
507 {
508 DWORD ret;
509
510 TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx, family %ld, class %ld\n",
511 ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags, family, class);
512 if (!ppUdpTable)
513 ret = ERROR_INVALID_PARAMETER;
514 else {
515 DWORD dwSize = 0;
516
517 *ppUdpTable = NULL;
518 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0);
519 if (ret == ERROR_INSUFFICIENT_BUFFER) {
520 *ppUdpTable = HeapAlloc(heap, flags, dwSize);
521 ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0);
522 if (ret != NO_ERROR) {
523 HeapFree(heap, flags, *ppUdpTable);
524 *ppUdpTable = NULL;
525 }
526 }
527 }
528 TRACE("returning %ld\n", ret);
529 return ret;
530 }
531
532
533 /******************************************************************
534 * CreateIpForwardEntry (IPHLPAPI.@)
535 *
536 *
537 * PARAMS
538 *
539 * pRoute [In/Out]
540 *
541 * RETURNS
542 *
543 * DWORD
544 *
545 */
546 DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
547 {
548 return createIpForwardEntry( pRoute );
549 }
550
551
552 /******************************************************************
553 * CreateIpNetEntry (IPHLPAPI.@)
554 *
555 *
556 * PARAMS
557 *
558 * pArpEntry [In/Out]
559 *
560 * RETURNS
561 *
562 * DWORD
563 *
564 */
565 DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
566 {
567 TRACE("pArpEntry %p\n", pArpEntry);
568 /* could use SIOCSARP on systems that support it, not sure I want to */
569 FIXME(":stub\n");
570 return (DWORD) 0;
571 }
572
573
574 /******************************************************************
575 * CreateProxyArpEntry (IPHLPAPI.@)
576 *
577 *
578 * PARAMS
579 *
580 * dwAddress [In]
581 * dwMask [In]
582 * dwIfIndex [In]
583 *
584 * RETURNS
585 *
586 * DWORD
587 *
588 */
589 DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
590 {
591 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
592 dwMask, dwIfIndex);
593 FIXME(":stub\n");
594 /* marking Win2K+ functions not supported */
595 return ERROR_NOT_SUPPORTED;
596 }
597
598
599 /******************************************************************
600 * DeleteIPAddress (IPHLPAPI.@)
601 *
602 *
603 * PARAMS
604 *
605 * NTEContext [In]
606 *
607 * RETURNS
608 *
609 * DWORD
610 *
611 */
612 DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
613 {
614 TRACE("NTEContext %ld\n", NTEContext);
615 return RtlNtStatusToDosError(deleteIpAddress(NTEContext));
616 }
617
618
619 /******************************************************************
620 * DeleteIpForwardEntry (IPHLPAPI.@)
621 *
622 *
623 * PARAMS
624 *
625 * pRoute [In/Out]
626 *
627 * RETURNS
628 *
629 * DWORD
630 *
631 */
632 DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
633 {
634 return deleteIpForwardEntry( pRoute );
635 }
636
637
638 /******************************************************************
639 * DeleteIpNetEntry (IPHLPAPI.@)
640 *
641 *
642 * PARAMS
643 *
644 * pArpEntry [In/Out]
645 *
646 * RETURNS
647 *
648 * DWORD
649 *
650 */
651 DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
652 {
653 TRACE("pArpEntry %p\n", pArpEntry);
654 /* could use SIOCDARP on systems that support it, not sure I want to */
655 FIXME(":stub\n");
656 return (DWORD) 0;
657 }
658
659
660 /******************************************************************
661 * DeleteProxyArpEntry (IPHLPAPI.@)
662 *
663 *
664 * PARAMS
665 *
666 * dwAddress [In]
667 * dwMask [In]
668 * dwIfIndex [In]
669 *
670 * RETURNS
671 *
672 * DWORD
673 *
674 */
675 DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
676 {
677 TRACE("dwAddress 0x%08lx, dwMask 0x%08lx, dwIfIndex 0x%08lx\n", dwAddress,
678 dwMask, dwIfIndex);
679 FIXME(":stub\n");
680 /* marking Win2K+ functions not supported */
681 return ERROR_NOT_SUPPORTED;
682 }
683
684 /******************************************************************
685 * EnableRouter (IPHLPAPI.@)
686 *
687 *
688 * PARAMS
689 *
690 * pHandle [In/Out]
691 * pOverlapped [In/Out]
692 *
693 * RETURNS
694 *
695 * DWORD
696 *
697 */
698 DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped)
699 {
700 TRACE("pHandle %p, pOverlapped %p\n", pHandle, pOverlapped);
701 FIXME(":stub\n");
702 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
703 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
704 marking Win2K+ functions not supported */
705 return ERROR_NOT_SUPPORTED;
706 }
707
708
709 /******************************************************************
710 * FlushIpNetTable (IPHLPAPI.@)
711 *
712 *
713 * PARAMS
714 *
715 * dwIfIndex [In]
716 *
717 * RETURNS
718 *
719 * DWORD
720 *
721 */
722 DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex)
723 {
724 TRACE("dwIfIndex 0x%08lx\n", dwIfIndex);
725 FIXME(":stub\n");
726 /* this flushes the arp cache of the given index
727 marking Win2K+ functions not supported */
728 return ERROR_NOT_SUPPORTED;
729 }
730
731
732 /******************************************************************
733 * GetAdapterIndex (IPHLPAPI.@)
734 *
735 *
736 * PARAMS
737 *
738 * AdapterName [In/Out]
739 * IfIndex [In/Out]
740 *
741 * RETURNS
742 *
743 * DWORD
744 *
745 */
746 DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
747 {
748 TRACE("AdapterName %p, IfIndex %p\n", AdapterName, IfIndex);
749 FIXME(":stub\n");
750 /* marking Win2K+ functions not supported */
751 return ERROR_NOT_SUPPORTED;
752 }
753
754
755 /******************************************************************
756 * GetAdaptersInfo (IPHLPAPI.@)
757 *
758 *
759 * PARAMS
760 *
761 * pAdapterInfo [In/Out]
762 * pOutBufLen [In/Out]
763 *
764 * RETURNS
765 *
766 * DWORD
767 *
768 */
769 DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
770 {
771 DWORD ret;
772 BOOL dhcpEnabled;
773 DWORD dhcpServer;
774
775 TRACE("pAdapterInfo %p, pOutBufLen %p\n", pAdapterInfo, pOutBufLen);
776 if (!pOutBufLen)
777 ret = ERROR_INVALID_PARAMETER;
778 else {
779 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
780
781 if (numNonLoopbackInterfaces > 0) {
782 /* this calculation assumes only one address in the IP_ADDR_STRING lists.
783 that's okay, because:
784 - we don't get multiple addresses per adapter anyway
785 - we don't know about per-adapter gateways
786 - DHCP and WINS servers can have max one entry per list */
787 ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces;
788
789 if (!pAdapterInfo || *pOutBufLen < size) {
790 *pOutBufLen = size;
791 ret = ERROR_BUFFER_OVERFLOW;
792 }
793 else {
794 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
795
796 if (table) {
797 size = sizeof(IP_ADAPTER_INFO) * table->numIndexes;
798 if (*pOutBufLen < size) {
799 *pOutBufLen = size;
800 ret = ERROR_INSUFFICIENT_BUFFER;
801 }
802 else {
803 DWORD ndx;
804 HKEY hKey;
805 BOOL winsEnabled = FALSE;
806 IP_ADDRESS_STRING primaryWINS, secondaryWINS;
807
808 memset(pAdapterInfo, 0, size);
809 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
810 "Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ,
811 &hKey) == ERROR_SUCCESS) {
812 DWORD size = sizeof(primaryWINS.String);
813 unsigned long addr;
814
815 RegQueryValueExA(hKey, "WinsServer", NULL, NULL,
816 (PBYTE)primaryWINS.String, &size);
817 addr = inet_addr(primaryWINS.String);
818 if (addr != INADDR_NONE && addr != INADDR_ANY)
819 winsEnabled = TRUE;
820 size = sizeof(secondaryWINS.String);
821 RegQueryValueExA(hKey, "BackupWinsServer", NULL, NULL,
822 (PBYTE)secondaryWINS.String, &size);
823 addr = inet_addr(secondaryWINS.String);
824 if (addr != INADDR_NONE && addr != INADDR_ANY)
825 winsEnabled = TRUE;
826 RegCloseKey(hKey);
827 }
828 TRACE("num of index is %lu\n", table->numIndexes);
829 for (ndx = 0; ndx < table->numIndexes; ndx++) {
830 PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
831 DWORD addrLen = sizeof(ptr->Address), type;
832 const char *ifname =
833 getInterfaceNameByIndex(table->indexes[ndx]);
834 if (!ifname) {
835 ret = ERROR_OUTOFMEMORY;
836 break;
837 }
838
839 /* on Win98 this is left empty, but whatever */
840 strncpy(ptr->AdapterName,ifname,sizeof(ptr->AdapterName));
841 consumeInterfaceName(ifname);
842 ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0';
843 getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen,
844 ptr->Address, &type);
845 /* MS defines address length and type as UINT in some places and
846 DWORD in others, **sigh**. Don't want to assume that PUINT and
847 PDWORD are equiv (64-bit?) */
848 ptr->AddressLength = addrLen;
849 ptr->Type = type;
850 ptr->Index = table->indexes[ndx];
851 toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]),
852 ptr->IpAddressList.IpAddress.String);
853 toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]),
854 ptr->IpAddressList.IpMask.String);
855 ptr->IpAddressList.Context = ptr->Index;
856 toIPAddressString(getInterfaceGatewayByIndex(table->indexes[ndx]),
857 ptr->GatewayList.IpAddress.String);
858 getDhcpInfoForAdapter(table->indexes[ndx], &dhcpEnabled,
859 &dhcpServer, &ptr->LeaseObtained,
860 &ptr->LeaseExpires);
861 ptr->DhcpEnabled = (DWORD) dhcpEnabled;
862 toIPAddressString(dhcpServer,
863 ptr->DhcpServer.IpAddress.String);
864 if (winsEnabled) {
865 ptr->HaveWins = TRUE;
866 memcpy(ptr->PrimaryWinsServer.IpAddress.String,
867 primaryWINS.String, sizeof(primaryWINS.String));
868 memcpy(ptr->SecondaryWinsServer.IpAddress.String,
869 secondaryWINS.String, sizeof(secondaryWINS.String));
870 }
871 if (ndx < table->numIndexes - 1)
872 ptr->Next = &pAdapterInfo[ndx + 1];
873 else
874 ptr->Next = NULL;
875 }
876 ret = NO_ERROR;
877 }
878 free(table);
879 }
880 else
881 ret = ERROR_OUTOFMEMORY;
882 }
883 }
884 else
885 ret = ERROR_NO_DATA;
886 }
887 TRACE("returning %ld\n", ret);
888 return ret;
889 }
890
891
892 /******************************************************************
893 * GetBestInterface (IPHLPAPI.@)
894 *
895 *
896 * PARAMS
897 *
898 * dwDestAddr [In]
899 * pdwBestIfIndex [In/Out]
900 *
901 * RETURNS
902 *
903 * DWORD
904 *
905 */
906 DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
907 {
908 DWORD ret;
909
910 TRACE("dwDestAddr 0x%08lx, pdwBestIfIndex %p\n", dwDestAddr, pdwBestIfIndex);
911 if (!pdwBestIfIndex)
912 ret = ERROR_INVALID_PARAMETER;
913 else {
914 MIB_IPFORWARDROW ipRow;
915
916 ret = GetBestRoute(dwDestAddr, 0, &ipRow);
917 if (ret == ERROR_SUCCESS)
918 *pdwBestIfIndex = ipRow.dwForwardIfIndex;
919 }
920 TRACE("returning %ld\n", ret);
921 return ret;
922 }
923
924
925 /******************************************************************
926 * GetBestRoute (IPHLPAPI.@)
927 *
928 *
929 * PARAMS
930 *
931 * dwDestAddr [In]
932 * dwSourceAddr [In]
933 * OUT [In]
934 *
935 * RETURNS
936 *
937 * DWORD
938 *
939 */
940 DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute)
941 {
942 PMIB_IPFORWARDTABLE table;
943 DWORD ret;
944
945 TRACE("dwDestAddr 0x%08lx, dwSourceAddr 0x%08lx, pBestRoute %p\n", dwDestAddr,
946 dwSourceAddr, pBestRoute);
947 if (!pBestRoute)
948 return ERROR_INVALID_PARAMETER;
949
950 AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
951 if (table) {
952 DWORD ndx, minMaskSize, matchedNdx = 0;
953
954 for (ndx = 0, minMaskSize = 255; ndx < table->dwNumEntries; ndx++) {
955 if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
956 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
957 DWORD hostMaskSize;
958
959 if (!_BitScanForward(&hostMaskSize, ntohl(table->table[ndx].dwForwardMask)))
960 {
961 hostMaskSize = 32;
962 }
963 if (hostMaskSize < minMaskSize) {
964 minMaskSize = hostMaskSize;
965 matchedNdx = ndx;
966 }
967 }
968 }
969 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW));
970 HeapFree(GetProcessHeap(), 0, table);
971 ret = ERROR_SUCCESS;
972 }
973 else
974 ret = ERROR_OUTOFMEMORY;
975 TRACE("returning %ld\n", ret);
976 return ret;
977 }
978
979 static int TcpTableSorter(const void *a, const void *b)
980 {
981 int ret;
982
983 if (a && b) {
984 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
985
986 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
987 if (ret == 0) {
988 ret = rowA->dwLocalPort - rowB->dwLocalPort;
989 if (ret == 0) {
990 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
991 if (ret == 0)
992 ret = rowA->dwRemotePort - rowB->dwRemotePort;
993 }
994 }
995 }
996 else
997 ret = 0;
998 return ret;
999 }
1000
1001 /******************************************************************
1002 * GetExtendedTcpTable (IPHLPAPI.@)
1003 *
1004 * Get the table of TCP endpoints available to the application.
1005 *
1006 * PARAMS
1007 * pTcpTable [Out] table struct with the filtered TCP endpoints available to application
1008 * pdwSize [In/Out] estimated size of the structure returned in pTcpTable, in bytes
1009 * bOrder [In] whether to order the table
1010 * ulAf [in] version of IP used by the TCP endpoints
1011 * TableClass [in] type of the TCP table structure from TCP_TABLE_CLASS
1012 * Reserved [in] reserved - this value must be zero
1013 *
1014 * RETURNS
1015 * Success: NO_ERROR
1016 * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER
1017 *
1018 * NOTES
1019 */
1020
1021 DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved)
1022 {
1023 DWORD i, count;
1024 DWORD ret = NO_ERROR;
1025
1026 if (!pdwSize)
1027 {
1028 return ERROR_INVALID_PARAMETER;
1029 }
1030
1031 if (ulAf != AF_INET)
1032 {
1033 UNIMPLEMENTED;
1034 return ERROR_INVALID_PARAMETER;
1035 }
1036
1037 switch (TableClass)
1038 {
1039 case TCP_TABLE_BASIC_ALL:
1040 {
1041 PMIB_TCPTABLE pOurTcpTable = getTcpTable();
1042 PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
1043
1044 if (pOurTcpTable)
1045 {
1046 if (sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW) > *pdwSize || !pTheirTcpTable)
1047 {
1048 *pdwSize = sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW);
1049 ret = ERROR_INSUFFICIENT_BUFFER;
1050 }
1051 else
1052 {
1053 memcpy(pTheirTcpTable, pOurTcpTable, sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW));
1054
1055 if (bOrder)
1056 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1057 sizeof(MIB_TCPROW), TcpTableSorter);
1058 }
1059
1060 free(pOurTcpTable);
1061 }
1062 }
1063 break;
1064
1065 case TCP_TABLE_BASIC_CONNECTIONS:
1066 {
1067 PMIB_TCPTABLE pOurTcpTable = getTcpTable();
1068 PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
1069
1070 if (pOurTcpTable)
1071 {
1072 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1073 {
1074 if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN)
1075 {
1076 ++count;
1077 }
1078 }
1079
1080 if (sizeof(DWORD) + count * sizeof(MIB_TCPROW) > *pdwSize || !pTheirTcpTable)
1081 {
1082 *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW);
1083 ret = ERROR_INSUFFICIENT_BUFFER;
1084 }
1085 else
1086 {
1087 pTheirTcpTable->dwNumEntries = count;
1088
1089 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1090 {
1091 if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN)
1092 {
1093 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW));
1094 ++count;
1095 }
1096 }
1097 ASSERT(count == pTheirTcpTable->dwNumEntries);
1098
1099 if (bOrder)
1100 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1101 sizeof(MIB_TCPROW), TcpTableSorter);
1102 }
1103
1104 free(pOurTcpTable);
1105 }
1106 }
1107 break;
1108
1109 case TCP_TABLE_BASIC_LISTENER:
1110 {
1111 PMIB_TCPTABLE pOurTcpTable = getTcpTable();
1112 PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
1113
1114 if (pOurTcpTable)
1115 {
1116 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1117 {
1118 if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN)
1119 {
1120 ++count;
1121 }
1122 }
1123
1124 if (sizeof(DWORD) + count * sizeof(MIB_TCPROW) > *pdwSize || !pTheirTcpTable)
1125 {
1126 *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW);
1127 ret = ERROR_INSUFFICIENT_BUFFER;
1128 }
1129 else
1130 {
1131 pTheirTcpTable->dwNumEntries = count;
1132
1133 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1134 {
1135 if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN)
1136 {
1137 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW));
1138 ++count;
1139 }
1140 }
1141 ASSERT(count == pTheirTcpTable->dwNumEntries);
1142
1143 if (bOrder)
1144 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1145 sizeof(MIB_TCPROW), TcpTableSorter);
1146 }
1147
1148 free(pOurTcpTable);
1149 }
1150 }
1151 break;
1152
1153 case TCP_TABLE_OWNER_PID_ALL:
1154 {
1155 PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getOwnerTcpTable();
1156 PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable;
1157
1158 if (pOurTcpTable)
1159 {
1160 if (sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID) > *pdwSize || !pTheirTcpTable)
1161 {
1162 *pdwSize = sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID);
1163 ret = ERROR_INSUFFICIENT_BUFFER;
1164 }
1165 else
1166 {
1167 memcpy(pTheirTcpTable, pOurTcpTable, sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID));
1168
1169 /* Don't sort on PID, so use basic helper */
1170 if (bOrder)
1171 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1172 sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter);
1173 }
1174
1175 free(pOurTcpTable);
1176 }
1177 }
1178 break;
1179
1180 case TCP_TABLE_OWNER_PID_CONNECTIONS:
1181 {
1182 PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getOwnerTcpTable();
1183 PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable;
1184
1185 if (pOurTcpTable)
1186 {
1187 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1188 {
1189 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
1190 {
1191 ++count;
1192 }
1193 }
1194
1195 if (sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_PID) > *pdwSize || !pTheirTcpTable)
1196 {
1197 *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_PID);
1198 ret = ERROR_INSUFFICIENT_BUFFER;
1199 }
1200 else
1201 {
1202 pTheirTcpTable->dwNumEntries = count;
1203
1204 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1205 {
1206 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
1207 {
1208 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_PID));
1209 ++count;
1210 }
1211 }
1212 ASSERT(count == pTheirTcpTable->dwNumEntries);
1213
1214 /* Don't sort on PID, so use basic helper */
1215 if (bOrder)
1216 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1217 sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter);
1218 }
1219
1220 free(pOurTcpTable);
1221 }
1222 }
1223 break;
1224
1225 case TCP_TABLE_OWNER_PID_LISTENER:
1226 {
1227 PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getOwnerTcpTable();
1228 PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable;
1229
1230 if (pOurTcpTable)
1231 {
1232 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1233 {
1234 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
1235 {
1236 ++count;
1237 }
1238 }
1239
1240 if (sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_PID) > *pdwSize || !pTheirTcpTable)
1241 {
1242 *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_PID);
1243 ret = ERROR_INSUFFICIENT_BUFFER;
1244 }
1245 else
1246 {
1247 pTheirTcpTable->dwNumEntries = count;
1248
1249 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1250 {
1251 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
1252 {
1253 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_PID));
1254 ++count;
1255 }
1256 }
1257 ASSERT(count == pTheirTcpTable->dwNumEntries);
1258
1259 /* Don't sort on PID, so use basic helper */
1260 if (bOrder)
1261 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1262 sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter);
1263 }
1264
1265 free(pOurTcpTable);
1266 }
1267 }
1268 break;
1269
1270 case TCP_TABLE_OWNER_MODULE_ALL:
1271 {
1272 PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getOwnerModTcpTable();
1273 PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
1274
1275 if (pOurTcpTable)
1276 {
1277 if (sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE) > *pdwSize || !pTheirTcpTable)
1278 {
1279 *pdwSize = sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE);
1280 ret = ERROR_INSUFFICIENT_BUFFER;
1281 }
1282 else
1283 {
1284 memcpy(pTheirTcpTable, pOurTcpTable, sizeof(DWORD) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE));
1285
1286 /* Don't sort on PID, so use basic helper */
1287 if (bOrder)
1288 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1289 sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
1290 }
1291
1292 free(pOurTcpTable);
1293 }
1294 }
1295 break;
1296
1297 case TCP_TABLE_OWNER_MODULE_CONNECTIONS:
1298 {
1299 PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getOwnerModTcpTable();
1300 PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
1301
1302 if (pOurTcpTable)
1303 {
1304 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1305 {
1306 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
1307 {
1308 ++count;
1309 }
1310 }
1311
1312 if (sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE) > *pdwSize || !pTheirTcpTable)
1313 {
1314 *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE);
1315 ret = ERROR_INSUFFICIENT_BUFFER;
1316 }
1317 else
1318 {
1319 pTheirTcpTable->dwNumEntries = count;
1320
1321 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1322 {
1323 if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
1324 {
1325 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE));
1326 ++count;
1327 }
1328 }
1329 ASSERT(count == pTheirTcpTable->dwNumEntries);
1330
1331 /* Don't sort on PID, so use basic helper */
1332 if (bOrder)
1333 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1334 sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
1335 }
1336
1337 free(pOurTcpTable);
1338 }
1339 }
1340 break;
1341
1342 case TCP_TABLE_OWNER_MODULE_LISTENER:
1343 {
1344 PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getOwnerModTcpTable();
1345 PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
1346
1347 if (pOurTcpTable)
1348 {
1349 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1350 {
1351 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
1352 {
1353 ++count;
1354 }
1355 }
1356
1357 if (sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE) > *pdwSize || !pTheirTcpTable)
1358 {
1359 *pdwSize = sizeof(DWORD) + count * sizeof(MIB_TCPROW_OWNER_MODULE);
1360 ret = ERROR_INSUFFICIENT_BUFFER;
1361 }
1362 else
1363 {
1364 pTheirTcpTable->dwNumEntries = count;
1365
1366 for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
1367 {
1368 if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
1369 {
1370 memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE));
1371 ++count;
1372 }
1373 }
1374 ASSERT(count == pTheirTcpTable->dwNumEntries);
1375
1376 /* Don't sort on PID, so use basic helper */
1377 if (bOrder)
1378 qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
1379 sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
1380 }
1381
1382 free(pOurTcpTable);
1383 }
1384 }
1385 break;
1386
1387 default:
1388 ret = ERROR_INVALID_PARAMETER;
1389 break;
1390 }
1391
1392 return ret;
1393 }
1394
1395
1396 static int UdpTableSorter(const void *a, const void *b)
1397 {
1398 int ret;
1399
1400 if (a && b) {
1401 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1402
1403 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1404 if (ret == 0)
1405 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1406 }
1407 else
1408 ret = 0;
1409 return ret;
1410 }
1411
1412 /******************************************************************
1413 * GetExtendedUdpTable (IPHLPAPI.@)
1414 *
1415 * Get the table of UDP endpoints available to the application.
1416 *
1417 * PARAMS
1418 * pUdpTable [Out] table struct with the filtered UDP endpoints available to application
1419 * pdwSize [In/Out] estimated size of the structure returned in pUdpTable, in bytes
1420 * bOrder [In] whether to order the table
1421 * ulAf [in] version of IP used by the UDP endpoints
1422 * TableClass [in] type of the UDP table structure from UDP_TABLE_CLASS
1423 * Reserved [in] reserved - this value must be zero
1424 *
1425 * RETURNS
1426 * Success: NO_ERROR
1427 * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER
1428 *
1429 * NOTES
1430 */
1431
1432 DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved)
1433 {
1434 DWORD ret = NO_ERROR;
1435
1436 if (!pdwSize)
1437 {
1438 return ERROR_INVALID_PARAMETER;
1439 }
1440
1441 if (ulAf != AF_INET)
1442 {
1443 UNIMPLEMENTED;
1444 return ERROR_INVALID_PARAMETER;
1445 }
1446
1447 switch (TableClass)
1448 {
1449 case UDP_TABLE_BASIC:
1450 {
1451 PMIB_UDPTABLE pOurUdpTable = getUdpTable();
1452 PMIB_UDPTABLE pTheirUdpTable = pUdpTable;
1453
1454 if (pOurUdpTable)
1455 {
1456 if (sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW) > *pdwSize || !pTheirUdpTable)
1457 {
1458 *pdwSize = sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW);
1459 ret = ERROR_INSUFFICIENT_BUFFER;
1460 }
1461 else
1462 {
1463 memcpy(pTheirUdpTable, pOurUdpTable, sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID));
1464
1465 if (bOrder)
1466 qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries,
1467 sizeof(MIB_UDPROW), UdpTableSorter);
1468 }
1469
1470 free(pOurUdpTable);
1471 }
1472 }
1473 break;
1474
1475 case UDP_TABLE_OWNER_PID:
1476 {
1477 PMIB_UDPTABLE_OWNER_PID pOurUdpTable = getOwnerUdpTable();
1478 PMIB_UDPTABLE_OWNER_PID pTheirUdpTable = pUdpTable;
1479
1480 if (pOurUdpTable)
1481 {
1482 if (sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID) > *pdwSize || !pTheirUdpTable)
1483 {
1484 *pdwSize = sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID);
1485 ret = ERROR_INSUFFICIENT_BUFFER;
1486 }
1487 else
1488 {
1489 memcpy(pTheirUdpTable, pOurUdpTable, sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID));
1490
1491 if (bOrder)
1492 qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries,
1493 sizeof(MIB_UDPROW_OWNER_PID), UdpTableSorter);
1494 }
1495
1496 free(pOurUdpTable);
1497 }
1498 }
1499 break;
1500
1501 case UDP_TABLE_OWNER_MODULE:
1502 {
1503 PMIB_UDPTABLE_OWNER_MODULE pOurUdpTable = getOwnerModUdpTable();
1504 PMIB_UDPTABLE_OWNER_MODULE pTheirUdpTable = pUdpTable;
1505
1506 if (pOurUdpTable)
1507 {
1508 if (sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE) > *pdwSize || !pTheirUdpTable)
1509 {
1510 *pdwSize = sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE);
1511 ret = ERROR_INSUFFICIENT_BUFFER;
1512 }
1513 else
1514 {
1515 memcpy(pTheirUdpTable, pOurUdpTable, sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE));
1516
1517 if (bOrder)
1518 qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries,
1519 sizeof(MIB_UDPROW_OWNER_MODULE), UdpTableSorter);
1520 }
1521
1522 free(pOurUdpTable);
1523 }
1524 }
1525 break;
1526
1527 default:
1528 ret = ERROR_INVALID_PARAMETER;
1529 break;
1530 }
1531
1532 return ret;
1533 }
1534
1535
1536 /******************************************************************
1537 * GetFriendlyIfIndex (IPHLPAPI.@)
1538 *
1539 *
1540 * PARAMS
1541 *
1542 * IfIndex [In]
1543 *
1544 * RETURNS
1545 *
1546 * DWORD
1547 *
1548 */
1549 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
1550 {
1551 /* windows doesn't validate these, either, just makes sure the top byte is
1552 cleared. I assume my ifenum module never gives an index with the top
1553 byte set. */
1554 TRACE("returning %ld\n", IfIndex);
1555 return IfIndex;
1556 }
1557
1558
1559 /******************************************************************
1560 * GetIcmpStatistics (IPHLPAPI.@)
1561 *
1562 *
1563 * PARAMS
1564 *
1565 * pStats [In/Out]
1566 *
1567 * RETURNS
1568 *
1569 * DWORD
1570 *
1571 */
1572 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
1573 {
1574 DWORD ret;
1575
1576 TRACE("pStats %p\n", pStats);
1577 ret = getICMPStats(pStats);
1578 TRACE("returning %ld\n", ret);
1579 return ret;
1580 }
1581
1582
1583 /******************************************************************
1584 * GetIfEntry (IPHLPAPI.@)
1585 *
1586 *
1587 * PARAMS
1588 *
1589 * pIfRow [In/Out]
1590 *
1591 * RETURNS
1592 *
1593 * DWORD
1594 *
1595 */
1596 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
1597 {
1598 DWORD ret;
1599 const char *name;
1600
1601 TRACE("pIfRow %p\n", pIfRow);
1602 if (!pIfRow)
1603 return ERROR_INVALID_PARAMETER;
1604
1605 name = getInterfaceNameByIndex(pIfRow->dwIndex);
1606 if (name) {
1607 ret = getInterfaceEntryByIndex(pIfRow->dwIndex, pIfRow);
1608 if (ret == NO_ERROR)
1609 ret = getInterfaceStatsByName(name, pIfRow);
1610 consumeInterfaceName(name);
1611 }
1612 else
1613 ret = ERROR_INVALID_DATA;
1614 TRACE("returning %ld\n", ret);
1615 return ret;
1616 }
1617
1618
1619 static int IfTableSorter(const void *a, const void *b)
1620 {
1621 int ret;
1622
1623 if (a && b)
1624 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex;
1625 else
1626 ret = 0;
1627 return ret;
1628 }
1629
1630
1631 /******************************************************************
1632 * GetIfTable (IPHLPAPI.@)
1633 *
1634 *
1635 * PARAMS
1636 *
1637 * pIfTable [In/Out]
1638 * pdwSize [In/Out]
1639 * bOrder [In]
1640 *
1641 * RETURNS
1642 *
1643 * DWORD
1644 *
1645 */
1646 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
1647 {
1648 DWORD ret;
1649
1650 TRACE("pIfTable %p, pdwSize %p, bOrder %ld\n", pdwSize, pdwSize,
1651 (DWORD)bOrder);
1652 if (!pdwSize)
1653 ret = ERROR_INVALID_PARAMETER;
1654 else {
1655 DWORD numInterfaces = getNumInterfaces();
1656 ULONG size;
1657 TRACE("GetIfTable: numInterfaces = %d\n", (int)numInterfaces);
1658 size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW);
1659
1660 if (!pIfTable || *pdwSize < size) {
1661 *pdwSize = size;
1662 ret = ERROR_INSUFFICIENT_BUFFER;
1663 }
1664 else {
1665 InterfaceIndexTable *table = getInterfaceIndexTable();
1666
1667 if (table) {
1668 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) *
1669 sizeof(MIB_IFROW);
1670 if (*pdwSize < size) {
1671 *pdwSize = size;
1672 ret = ERROR_INSUFFICIENT_BUFFER;
1673 }
1674 else {
1675 DWORD ndx;
1676
1677 pIfTable->dwNumEntries = 0;
1678 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1679 pIfTable->table[ndx].dwIndex = table->indexes[ndx];
1680 GetIfEntry(&pIfTable->table[ndx]);
1681 pIfTable->dwNumEntries++;
1682 }
1683 if (bOrder)
1684 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
1685 IfTableSorter);
1686 ret = NO_ERROR;
1687 }
1688 free(table);
1689 }
1690 else
1691 ret = ERROR_OUTOFMEMORY;
1692 }
1693 }
1694 TRACE("returning %ld\n", ret);
1695 return ret;
1696 }
1697
1698
1699 /******************************************************************
1700 * GetInterfaceInfo (IPHLPAPI.@)
1701 *
1702 *
1703 * PARAMS
1704 *
1705 * pIfTable [In/Out]
1706 * dwOutBufLen [In/Out]
1707 *
1708 * RETURNS
1709 *
1710 * DWORD
1711 *
1712 */
1713 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
1714 {
1715 DWORD ret;
1716
1717 TRACE("pIfTable %p, dwOutBufLen %p\n", pIfTable, dwOutBufLen);
1718 if (!dwOutBufLen)
1719 ret = ERROR_INVALID_PARAMETER;
1720 else {
1721 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
1722 ULONG size;
1723 TRACE("numNonLoopbackInterfaces == 0x%x\n", numNonLoopbackInterfaces);
1724 size = sizeof(IP_INTERFACE_INFO) + (numNonLoopbackInterfaces) *
1725 sizeof(IP_ADAPTER_INDEX_MAP);
1726
1727 if (!pIfTable || *dwOutBufLen < size) {
1728 *dwOutBufLen = size;
1729 ret = ERROR_INSUFFICIENT_BUFFER;
1730 }
1731 else {
1732 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
1733
1734 if (table) {
1735 TRACE("table->numIndexes == 0x%x\n", table->numIndexes);
1736 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes) *
1737 sizeof(IP_ADAPTER_INDEX_MAP);
1738 if (*dwOutBufLen < size) {
1739 *dwOutBufLen = size;
1740 ret = ERROR_INSUFFICIENT_BUFFER;
1741 }
1742 else {
1743 DWORD ndx;
1744
1745 pIfTable->NumAdapters = 0;
1746 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1747 const char *walker, *name;
1748 WCHAR *assigner;
1749
1750 pIfTable->Adapter[ndx].Index = table->indexes[ndx];
1751 name = getInterfaceNameByIndex(table->indexes[ndx]);
1752 for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
1753 walker && *walker &&
1754 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
1755 walker++, assigner++)
1756 *assigner = *walker;
1757 *assigner = 0;
1758 consumeInterfaceName(name);
1759 pIfTable->NumAdapters++;
1760 }
1761 ret = NO_ERROR;
1762 }
1763 free(table);
1764 }
1765 else
1766 ret = ERROR_OUTOFMEMORY;
1767 }
1768 }
1769 TRACE("returning %ld\n", ret);
1770 return ret;
1771 }
1772
1773
1774 static int IpAddrTableSorter(const void *a, const void *b)
1775 {
1776 int ret;
1777
1778 if (a && b)
1779 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr;
1780 else
1781 ret = 0;
1782 return ret;
1783 }
1784
1785
1786 /******************************************************************
1787 * GetIpAddrTable (IPHLPAPI.@)
1788 *
1789 *
1790 * PARAMS
1791 *
1792 * pIpAddrTable [In/Out]
1793 * pdwSize [In/Out]
1794 * bOrder [In]
1795 *
1796 * RETURNS
1797 *
1798 * DWORD
1799 *
1800 */
1801 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
1802 {
1803 DWORD ret;
1804
1805 TRACE("pIpAddrTable %p, pdwSize %p, bOrder %ld\n", pIpAddrTable, pdwSize,
1806 (DWORD)bOrder);
1807 if (!pdwSize)
1808 ret = ERROR_INVALID_PARAMETER;
1809 else {
1810 DWORD numInterfaces = getNumInterfaces();
1811 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) *
1812 sizeof(MIB_IPADDRROW);
1813
1814 if (!pIpAddrTable || *pdwSize < size) {
1815 *pdwSize = size;
1816 ret = ERROR_INSUFFICIENT_BUFFER;
1817 }
1818 else {
1819 InterfaceIndexTable *table = getInterfaceIndexTable();
1820
1821 if (table) {
1822 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) *
1823 sizeof(MIB_IPADDRROW);
1824 if (*pdwSize < size) {
1825 *pdwSize = size;
1826 ret = ERROR_INSUFFICIENT_BUFFER;
1827 }
1828 else {
1829 DWORD ndx, bcast;
1830
1831 pIpAddrTable->dwNumEntries = 0;
1832 for (ndx = 0; ndx < table->numIndexes; ndx++) {
1833 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx];
1834 pIpAddrTable->table[ndx].dwAddr =
1835 getInterfaceIPAddrByIndex(table->indexes[ndx]);
1836 pIpAddrTable->table[ndx].dwMask =
1837 getInterfaceMaskByIndex(table->indexes[ndx]);
1838 /* the dwBCastAddr member isn't the broadcast address, it indicates
1839 * whether the interface uses the 1's broadcast address (1) or the
1840 * 0's broadcast address (0).
1841 */
1842 bcast = getInterfaceBCastAddrByIndex(table->indexes[ndx]);
1843 pIpAddrTable->table[ndx].dwBCastAddr =
1844 (bcast & pIpAddrTable->table[ndx].dwMask) ? 1 : 0;
1845 /* FIXME: hardcoded reasm size, not sure where to get it */
1846 pIpAddrTable->table[ndx].dwReasmSize = 65535;
1847 pIpAddrTable->table[ndx].unused1 = 0;
1848 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */
1849 pIpAddrTable->dwNumEntries++;
1850 }
1851 if (bOrder)
1852 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries,
1853 sizeof(MIB_IPADDRROW), IpAddrTableSorter);
1854 ret = NO_ERROR;
1855 }
1856 free(table);
1857 }
1858 else
1859 ret = ERROR_OUTOFMEMORY;
1860 }
1861 }
1862 TRACE("returning %ld\n", ret);
1863 return ret;
1864 }
1865
1866
1867 static int IpForwardTableSorter(const void *a, const void *b)
1868 {
1869 int ret;
1870
1871 if (a && b) {
1872 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b;
1873
1874 ret = rowA->dwForwardDest - rowB->dwForwardDest;
1875 if (ret == 0) {
1876 ret = rowA->dwForwardProto - rowB->dwForwardProto;
1877 if (ret == 0) {
1878 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy;
1879 if (ret == 0)
1880 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop;
1881 }
1882 }
1883 }
1884 else
1885 ret = 0;
1886 return ret;
1887 }
1888
1889
1890 /******************************************************************
1891 * GetIpForwardTable (IPHLPAPI.@)
1892 *
1893 *
1894 * PARAMS
1895 *
1896 * pIpForwardTable [In/Out]
1897 * pdwSize [In/Out]
1898 * bOrder [In]
1899 *
1900 * RETURNS
1901 *
1902 * DWORD
1903 *
1904 */
1905 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
1906 {
1907 DWORD ret;
1908
1909 TRACE("pIpForwardTable %p, pdwSize %p, bOrder %ld\n", pIpForwardTable,
1910 pdwSize, (DWORD)bOrder);
1911 if (!pdwSize)
1912 ret = ERROR_INVALID_PARAMETER;
1913 else {
1914 DWORD numRoutes = getNumRoutes();
1915 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) *
1916 sizeof(MIB_IPFORWARDROW);
1917
1918 if (!pIpForwardTable || *pdwSize < sizeNeeded) {
1919 *pdwSize = sizeNeeded;
1920 ret = ERROR_INSUFFICIENT_BUFFER;
1921 }
1922 else {
1923 RouteTable *table = getRouteTable();
1924 if (table) {
1925 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) *
1926 sizeof(MIB_IPFORWARDROW);
1927 if (*pdwSize < sizeNeeded) {
1928 *pdwSize = sizeNeeded;
1929 ret = ERROR_INSUFFICIENT_BUFFER;
1930 }
1931 else {
1932 DWORD ndx;
1933
1934 pIpForwardTable->dwNumEntries = table->numRoutes;
1935 for (ndx = 0; ndx < numRoutes; ndx++) {
1936 pIpForwardTable->table[ndx].dwForwardIfIndex =
1937 table->routes[ndx].ifIndex;
1938 pIpForwardTable->table[ndx].dwForwardDest =
1939 table->routes[ndx].dest;
1940 pIpForwardTable->table[ndx].dwForwardMask =
1941 table->routes[ndx].mask;
1942 pIpForwardTable->table[ndx].dwForwardPolicy = 0;
1943 pIpForwardTable->table[ndx].dwForwardNextHop =
1944 table->routes[ndx].gateway;
1945 /* FIXME: this type is appropriate for local interfaces; may not
1946 always be appropriate */
1947 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
1948 /* FIXME: other protos might be appropriate, e.g. the default route
1949 is typically set with MIB_IPPROTO_NETMGMT instead */
1950 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL;
1951 /* punt on age and AS */
1952 pIpForwardTable->table[ndx].dwForwardAge = 0;
1953 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0;
1954 pIpForwardTable->table[ndx].dwForwardMetric1 =
1955 table->routes[ndx].metric;
1956 /* rest of the metrics are 0.. */
1957 pIpForwardTable->table[ndx].dwForwardMetric2 = 0;
1958 pIpForwardTable->table[ndx].dwForwardMetric3 = 0;
1959 pIpForwardTable->table[ndx].dwForwardMetric4 = 0;
1960 pIpForwardTable->table[ndx].dwForwardMetric5 = 0;
1961 }
1962 if (bOrder)
1963 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
1964 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
1965 ret = NO_ERROR;
1966 }
1967 HeapFree(GetProcessHeap(), 0, table);
1968 }
1969 else
1970 ret = ERROR_OUTOFMEMORY;
1971 }
1972 }
1973 TRACE("returning %ld\n", ret);
1974 return ret;
1975 }
1976
1977
1978 static int IpNetTableSorter(const void *a, const void *b)
1979 {
1980 int ret;
1981
1982 if (a && b)
1983 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr;
1984 else
1985 ret = 0;
1986 return ret;
1987 }
1988
1989
1990 /******************************************************************
1991 * GetIpNetTable (IPHLPAPI.@)
1992 *
1993 *
1994 * PARAMS
1995 *
1996 * pIpNetTable [In/Out]
1997 * pdwSize [In/Out]
1998 * bOrder [In]
1999 *
2000 * RETURNS
2001 *
2002 * DWORD
2003 *
2004 */
2005 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
2006 {
2007 DWORD ret = NO_ERROR;
2008
2009 TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize,
2010 (DWORD)bOrder);
2011 if (!pdwSize)
2012 ret = ERROR_INVALID_PARAMETER;
2013 else {
2014 DWORD numEntries = getNumArpEntries();
2015 ULONG size = sizeof(MIB_IPNETTABLE);
2016
2017 if (numEntries > 1)
2018 size += (numEntries - 1) * sizeof(MIB_IPNETROW);
2019 if (!pIpNetTable || *pdwSize < size) {
2020 *pdwSize = size;
2021 ret = ERROR_INSUFFICIENT_BUFFER;
2022 }
2023 else {
2024 PMIB_IPNETTABLE table = getArpTable();
2025 if (table) {
2026 size = sizeof(MIB_IPNETTABLE);
2027 if (table->dwNumEntries > 1)
2028 size += (table->dwNumEntries - 1) * sizeof(MIB_IPNETROW);
2029 if (*pdwSize < size) {
2030 *pdwSize = size;
2031 ret = ERROR_INSUFFICIENT_BUFFER;
2032 }
2033 else {
2034 *pdwSize = size;
2035 memcpy(pIpNetTable, table, size);
2036 if (bOrder)
2037 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries,
2038 sizeof(MIB_IPNETROW), IpNetTableSorter);
2039 ret = NO_ERROR;
2040 }
2041 HeapFree(GetProcessHeap(), 0, table);
2042 }
2043 }
2044 }
2045 TRACE("returning %d\n", ret);
2046 return ret;
2047 }
2048
2049
2050 /******************************************************************
2051 * GetIpStatistics (IPHLPAPI.@)
2052 *
2053 *
2054 * PARAMS
2055 *
2056 * pStats [In/Out]
2057 *
2058 * RETURNS
2059 *
2060 * DWORD
2061 *
2062 */
2063 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
2064 {
2065 return GetIpStatisticsEx(pStats, PF_INET);
2066 }
2067
2068 /******************************************************************
2069 * GetIpStatisticsEx (IPHLPAPI.@)
2070 *
2071 *
2072 * PARAMS
2073 *
2074 * pStats [In/Out]
2075 * dwFamily [In]
2076 *
2077 * RETURNS
2078 *
2079 * DWORD
2080 *
2081 */
2082 DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
2083 {
2084 DWORD ret;
2085
2086 TRACE("pStats %p\n", pStats);
2087 ret = getIPStats(pStats, dwFamily);
2088 TRACE("returning %ld\n", ret);
2089 return ret;
2090 }
2091
2092 /******************************************************************
2093 * GetNetworkParams (IPHLPAPI.@)
2094 *
2095 *
2096 * PARAMS
2097 *
2098 * pFixedInfo [In/Out]
2099 * pOutBufLen [In/Out]
2100 *
2101 * RETURNS
2102 *
2103 * DWORD
2104 *
2105 */
2106 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
2107 {
2108 DWORD ret, size, type;
2109 LONG regReturn;
2110 HKEY hKey;
2111 PIPHLP_RES_INFO resInfo;
2112
2113 TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen);
2114 if (!pOutBufLen)
2115 return ERROR_INVALID_PARAMETER;
2116
2117 resInfo = getResInfo();
2118 if (!resInfo)
2119 return ERROR_OUTOFMEMORY;
2120
2121 size = sizeof(FIXED_INFO) + (resInfo->riCount > 1 ? (resInfo->riCount-1) *
2122 sizeof(IP_ADDR_STRING) : 0);
2123 if (!pFixedInfo || *pOutBufLen < size) {
2124 *pOutBufLen = size;
2125 disposeResInfo( resInfo );
2126 return ERROR_BUFFER_OVERFLOW;
2127 }
2128
2129 memset(pFixedInfo, 0, size);
2130 /* Check for DhcpHostname and DhcpDomain first */
2131 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2132 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
2133 0,
2134 KEY_READ,
2135 &hKey);
2136 if (regReturn == ERROR_SUCCESS) {
2137 /* Windows doesn't honor DHCP option 12 even if RFC requires it if it is returned by DHCP server! */
2138 #if 0
2139 type = REG_SZ;
2140 size = sizeof(pFixedInfo->HostName);
2141 regReturn = RegQueryValueExA(hKey,
2142 "DhcpHostname",
2143 NULL,
2144 &type,
2145 (LPBYTE)pFixedInfo->HostName,
2146 &size);
2147 if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1))
2148 {
2149 #endif
2150 type = REG_SZ;
2151 size = sizeof(pFixedInfo->HostName);
2152 regReturn = RegQueryValueExA(hKey,
2153 "Hostname",
2154 NULL,
2155 &type,
2156 (LPBYTE)pFixedInfo->HostName,
2157 &size);
2158 #if 0
2159 }
2160 #endif
2161
2162 type = REG_SZ;
2163 size = sizeof(pFixedInfo->DomainName);
2164 regReturn = RegQueryValueExA(hKey,
2165 "DhcpDomain",
2166 NULL,
2167 &type,
2168 (LPBYTE)pFixedInfo->DomainName,
2169 &size);
2170 if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1))
2171 {
2172 type = REG_SZ;
2173 size = sizeof(pFixedInfo->DomainName);
2174 regReturn = RegQueryValueExA(hKey,
2175 "Domain",
2176 NULL,
2177 &type,
2178 (LPBYTE)pFixedInfo->DomainName,
2179 &size);
2180 }
2181 RegCloseKey(hKey);
2182 }
2183
2184 TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName);
2185
2186 if (resInfo->riCount > 0)
2187 {
2188 CopyMemory(&pFixedInfo->DnsServerList, resInfo->DnsList, sizeof(IP_ADDR_STRING));
2189 if (resInfo->riCount > 1)
2190 {
2191 IP_ADDR_STRING *pSrc = resInfo->DnsList->Next;
2192 IP_ADDR_STRING *pTarget = (struct _IP_ADDR_STRING*)((char*)pFixedInfo + sizeof(FIXED_INFO));
2193
2194 pFixedInfo->DnsServerList.Next = pTarget;
2195
2196 do
2197 {
2198 CopyMemory(pTarget, pSrc, sizeof(IP_ADDR_STRING));
2199 resInfo->riCount--;
2200 if (resInfo->riCount > 1)
2201 {
2202 pTarget->Next = (IP_ADDR_STRING*)((char*)pTarget + sizeof(IP_ADDR_STRING));
2203 pTarget = pTarget->Next;
2204 pSrc = pSrc->Next;
2205 }
2206 else
2207 {
2208 pTarget->Next = NULL;
2209 break;
2210 }
2211 }
2212 while(TRUE);
2213 }
2214 else
2215 {
2216 pFixedInfo->DnsServerList.Next = NULL;
2217 }
2218 }
2219
2220 pFixedInfo->NodeType = HYBRID_NODETYPE;
2221 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2222 "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey);
2223 if (regReturn != ERROR_SUCCESS)
2224 regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2225 "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ,
2226 &hKey);
2227 if (regReturn == ERROR_SUCCESS)
2228 {
2229 DWORD size = sizeof(pFixedInfo->ScopeId);
2230
2231 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (PBYTE)pFixedInfo->ScopeId, &size);
2232 RegCloseKey(hKey);
2233 }
2234
2235 disposeResInfo( resInfo );
2236 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
2237 I suppose could also check for a listener on port 53 to set EnableDns */
2238 ret = NO_ERROR;
2239 TRACE("returning %ld\n", ret);
2240
2241 return ret;
2242 }
2243
2244
2245 /******************************************************************
2246 * GetNumberOfInterfaces (IPHLPAPI.@)
2247 *
2248 *
2249 * PARAMS
2250 *
2251 * pdwNumIf [In/Out]
2252 *
2253 * RETURNS
2254 *
2255 * DWORD
2256 *
2257 */
2258 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
2259 {
2260 DWORD ret;
2261
2262 TRACE("pdwNumIf %p\n", pdwNumIf);
2263 if (!pdwNumIf)
2264 ret = ERROR_INVALID_PARAMETER;
2265 else {
2266 *pdwNumIf = getNumInterfaces();
2267 ret = NO_ERROR;
2268 }
2269 TRACE("returning %ld\n", ret);
2270 return ret;
2271 }
2272
2273
2274 /******************************************************************
2275 * GetOwnerModuleFromTcpEntry (IPHLPAPI.@)
2276 *
2277 * Get data about the module that issued the context bind for a specific IPv4 TCP endpoint in a MIB table row
2278 *
2279 * PARAMS
2280 * pTcpEntry [in] pointer to a MIB_TCPROW_OWNER_MODULE structure
2281 * Class [in] TCPIP_OWNER_MODULE_INFO_CLASS enumeration value
2282 * Buffer [out] pointer a buffer containing a TCPIP_OWNER_MODULE_BASIC_INFO structure with the owner module data.
2283 * pdwSize [in, out] estimated size of the structure returned in Buffer, in bytes
2284 *
2285 * RETURNS
2286 * Success: NO_ERROR
2287 * Failure: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY
2288 * ERROR_NOT_FOUND or ERROR_PARTIAL_COPY
2289 *
2290 * NOTES
2291 * The type of data returned in Buffer is indicated by the value of the Class parameter.
2292 */
2293 DWORD WINAPI GetOwnerModuleFromTcpEntry( PMIB_TCPROW_OWNER_MODULE pTcpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
2294 {
2295 DWORD ret = NO_ERROR;
2296 UNIMPLEMENTED;
2297 return ret;
2298 }
2299
2300 static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, PVOID Data)
2301 {
2302 IP_ADDR_STRING *pNext;
2303 PNAME_SERVER_LIST_CONTEXT Context = (PNAME_SERVER_LIST_CONTEXT)Data;
2304
2305 if (!Context->NumServers)
2306 {
2307 if (Context->uSizeAvailable >= Context->uSizeRequired)
2308 {
2309 WideCharToMultiByte(CP_ACP, 0, Server, -1, Context->pData->DnsServerList.IpAddress.String, 16, NULL, NULL);
2310 Context->pData->DnsServerList.IpAddress.String[15] = '\0';
2311 Context->pLastAddr = &Context->pData->DnsServerList;
2312 }
2313 }
2314 else
2315 {
2316 Context->uSizeRequired += sizeof(IP_ADDR_STRING);
2317 if (Context->uSizeAvailable >= Context->uSizeRequired)
2318 {
2319 pNext = (IP_ADDR_STRING*)(((char*)Context->pLastAddr) + sizeof(IP_ADDR_STRING));
2320 WideCharToMultiByte(CP_ACP, 0, Server, -1, pNext->IpAddress.String, 16, NULL, NULL);
2321 pNext->IpAddress.String[15] = '\0';
2322 Context->pLastAddr->Next = pNext;
2323 Context->pLastAddr = pNext;
2324 pNext->Next = NULL;
2325 }
2326 }
2327 Context->NumServers++;
2328 }
2329
2330 /******************************************************************
2331 * GetPerAdapterInfo (IPHLPAPI.@)
2332 *
2333 *
2334 * PARAMS
2335 *
2336 * IfIndex [In]
2337 * pPerAdapterInfo [In/Out]
2338 * pOutBufLen [In/Out]
2339 *
2340 * RETURNS
2341 *
2342 * DWORD
2343 *
2344 */
2345 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
2346 {
2347 HKEY hkey;
2348 DWORD dwSize = 0;
2349 const char *ifName;
2350 NAME_SERVER_LIST_CONTEXT Context;
2351 WCHAR keyname[200] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
2352
2353 if (!pOutBufLen)
2354 return ERROR_INVALID_PARAMETER;
2355
2356 if (!pPerAdapterInfo || *pOutBufLen < sizeof(IP_PER_ADAPTER_INFO))
2357 {
2358 *pOutBufLen = sizeof(IP_PER_ADAPTER_INFO);
2359 return ERROR_BUFFER_OVERFLOW;
2360 }
2361
2362 ifName = getInterfaceNameByIndex(IfIndex);
2363 if (!ifName)
2364 return ERROR_INVALID_PARAMETER;
2365
2366 MultiByteToWideChar(CP_ACP, 0, ifName, -1, &keyname[62], sizeof(keyname)/sizeof(WCHAR) - 63);
2367 HeapFree(GetProcessHeap(), 0, (LPVOID)ifName);
2368
2369 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey) != ERROR_SUCCESS)
2370 {
2371 return ERROR_NOT_SUPPORTED;
2372 }
2373 Context.NumServers = 0;
2374 Context.uSizeAvailable = *pOutBufLen;
2375 Context.uSizeRequired = sizeof(IP_PER_ADAPTER_INFO);
2376 Context.pData = pPerAdapterInfo;
2377
2378 if (*pOutBufLen >= sizeof(IP_PER_ADAPTER_INFO))
2379 ZeroMemory(pPerAdapterInfo, sizeof(IP_PER_ADAPTER_INFO));
2380
2381 EnumNameServers(hkey, &keyname[62], &Context, CreateNameServerListEnumNamesFunc);
2382
2383 if (Context.uSizeRequired > Context.uSizeAvailable)
2384 {
2385 *pOutBufLen = Context.uSizeRequired;
2386 RegCloseKey(hkey);
2387 return ERROR_BUFFER_OVERFLOW;
2388 }
2389
2390 if(RegQueryValueExW(hkey, L"NameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
2391 {
2392 pPerAdapterInfo->AutoconfigActive = FALSE;
2393 }
2394 else
2395 {
2396 pPerAdapterInfo->AutoconfigActive = TRUE;
2397 }
2398
2399 RegCloseKey(hkey);
2400 return NOERROR;
2401 }
2402
2403
2404 /******************************************************************
2405 * GetRTTAndHopCount (IPHLPAPI.@)
2406 *
2407 *
2408 * PARAMS
2409 *
2410 * DestIpAddress [In]
2411 * HopCount [In/Out]
2412 * MaxHops [In]
2413 * RTT [In/Out]
2414 *
2415 * RETURNS
2416 *
2417 * BOOL
2418 *
2419 */
2420 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
2421 {
2422 TRACE("DestIpAddress 0x%08lx, HopCount %p, MaxHops %ld, RTT %p\n",
2423 DestIpAddress, HopCount, MaxHops, RTT);
2424 FIXME(":stub\n");
2425 return (BOOL) 0;
2426 }
2427
2428
2429 /******************************************************************
2430 * GetTcpStatisticsEx (IPHLPAPI.@)
2431 *
2432 *
2433 * PARAMS
2434 *
2435 * pStats [In/Out]
2436 * dwFamily [In]
2437 *
2438 * RETURNS
2439 *
2440 * DWORD
2441 *
2442 */
2443 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
2444 {
2445 DWORD ret;
2446
2447 TRACE("pStats %p\n", pStats);
2448 ret = getTCPStats(pStats, dwFamily);
2449 TRACE("returning %ld\n", ret);
2450 return ret;
2451 }
2452
2453 /******************************************************************
2454 * GetTcpStatistics (IPHLPAPI.@)
2455 *
2456 *
2457 * PARAMS
2458 *
2459 * pStats [In/Out]
2460 *
2461 * RETURNS
2462 *
2463 * DWORD
2464 *
2465 */
2466 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
2467 {
2468 return GetTcpStatisticsEx(pStats, PF_INET);
2469 }
2470
2471
2472 /******************************************************************
2473 * GetTcpTable (IPHLPAPI.@)
2474 *
2475 * Get the table of active TCP connections.
2476 *
2477 * PARAMS
2478 * pTcpTable [Out] buffer for TCP connections table
2479 * pdwSize [In/Out] length of output buffer
2480 * bOrder [In] whether to order the table
2481 *
2482 * RETURNS
2483 * Success: NO_ERROR
2484 * Failure: error code from winerror.h
2485 *
2486 * NOTES
2487 * If pdwSize is less than required, the function will return
2488 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to
2489 * the required byte size.
2490 * If bOrder is true, the returned table will be sorted, first by
2491 * local address and port number, then by remote address and port
2492 * number.
2493 */
2494 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
2495 {
2496 return GetExtendedTcpTable(pTcpTable, pdwSize, bOrder, AF_INET, TCP_TABLE_BASIC_ALL, 0);
2497 }
2498
2499
2500 /******************************************************************
2501 * GetUdpStatisticsEx (IPHLPAPI.@)
2502 *
2503 *
2504 * PARAMS
2505 *
2506 * pStats [In/Out]
2507 * dwFamily [In]
2508 *
2509 * RETURNS
2510 *
2511 * DWORD
2512 *
2513 */
2514 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
2515 {
2516 DWORD ret;
2517
2518 TRACE("pStats %p\n", pStats);
2519 ret = getUDPStats(pStats, dwFamily);
2520 TRACE("returning %ld\n", ret);
2521 return ret;
2522 }
2523
2524 /******************************************************************
2525 * GetUdpStatistics (IPHLPAPI.@)
2526 *
2527 *
2528 * PARAMS
2529 *
2530 * pStats [In/Out]
2531 *
2532 * RETURNS
2533 *
2534 * DWORD
2535 *
2536 */
2537 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
2538 {
2539 return GetUdpStatisticsEx(pStats, PF_INET);
2540 }
2541
2542
2543 /******************************************************************
2544 * GetUdpTable (IPHLPAPI.@)
2545 *
2546 *
2547 * PARAMS
2548 *
2549 * pUdpTable [In/Out]
2550 * pdwSize [In/Out]
2551 * bOrder [In]
2552 *
2553 * RETURNS
2554 *
2555 * DWORD
2556 *
2557 */
2558 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
2559 {
2560 return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, AF_INET, UDP_TABLE_BASIC, 0);
2561 }
2562
2563
2564 /******************************************************************
2565 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
2566 *
2567 * This is a Win98-only function to get information on "unidirectional"
2568 * adapters. Since this is pretty nonsensical in other contexts, it
2569 * never returns anything.
2570 *
2571 * PARAMS
2572 * pIPIfInfo [Out] buffer for adapter infos
2573 * dwOutBufLen [Out] length of the output buffer
2574 *
2575 * RETURNS
2576 * Success: NO_ERROR
2577 * Failure: error code from winerror.h
2578 *
2579 * FIXME
2580 * Stub, returns ERROR_NOT_SUPPORTED.
2581 */
2582 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
2583 {
2584 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo, dwOutBufLen);
2585 /* a unidirectional adapter?? not bloody likely! */
2586 return ERROR_NOT_SUPPORTED;
2587 }
2588
2589
2590 /******************************************************************
2591 * IpReleaseAddress (IPHLPAPI.@)
2592 *
2593 * Release an IP obtained through DHCP,
2594 *
2595 * PARAMS
2596 * AdapterInfo [In] adapter to release IP address
2597 *
2598 * RETURNS
2599 * Success: NO_ERROR
2600 * Failure: error code from winerror.h
2601 *
2602 */
2603 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
2604 {
2605 DWORD Status, Version = 0;
2606
2607 if (!AdapterInfo)
2608 return ERROR_INVALID_PARAMETER;
2609
2610 /* Maybe we should do this in DllMain */
2611 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
2612 return ERROR_PROC_NOT_FOUND;
2613
2614 if (DhcpReleaseIpAddressLease(AdapterInfo->Index))
2615 Status = ERROR_SUCCESS;
2616 else
2617 Status = ERROR_PROC_NOT_FOUND;
2618
2619 DhcpCApiCleanup();
2620
2621 return Status;
2622 }
2623
2624
2625 /******************************************************************
2626 * IpRenewAddress (IPHLPAPI.@)
2627 *
2628 * Renew an IP obtained through DHCP.
2629 *
2630 * PARAMS
2631 * AdapterInfo [In] adapter to renew IP address
2632 *
2633 * RETURNS
2634 * Success: NO_ERROR
2635 * Failure: error code from winerror.h
2636 */
2637 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
2638 {
2639 DWORD Status, Version = 0;
2640
2641 if (!AdapterInfo)
2642 return ERROR_INVALID_PARAMETER;
2643
2644 /* Maybe we should do this in DllMain */
2645 if (DhcpCApiInitialize(&Version) != ERROR_SUCCESS)
2646 return ERROR_PROC_NOT_FOUND;
2647
2648 if (DhcpRenewIpAddressLease(AdapterInfo->Index))
2649 Status = ERROR_SUCCESS;
2650 else
2651 Status = ERROR_PROC_NOT_FOUND;
2652
2653 DhcpCApiCleanup();
2654
2655 return Status;
2656 }
2657
2658
2659 /******************************************************************
2660 * NotifyAddrChange (IPHLPAPI.@)
2661 *
2662 * Notify caller whenever the ip-interface map is changed.
2663 *
2664 * PARAMS
2665 * Handle [Out] handle usable in asynchronous notification
2666 * overlapped [In] overlapped structure that notifies the caller
2667 *
2668 * RETURNS
2669 * Success: NO_ERROR
2670 * Failure: error code from winerror.h
2671 *
2672 * FIXME
2673 * Stub, returns ERROR_NOT_SUPPORTED.
2674 */
2675 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2676 {
2677 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2678 if (Handle) *Handle = INVALID_HANDLE_VALUE;
2679 if (overlapped) ((IO_STATUS_BLOCK *) overlapped)->Status = STATUS_PENDING;
2680 return ERROR_IO_PENDING;
2681 }
2682
2683
2684 /******************************************************************
2685 * NotifyRouteChange (IPHLPAPI.@)
2686 *
2687 * Notify caller whenever the ip routing table is changed.
2688 *
2689 * PARAMS
2690 * Handle [Out] handle usable in asynchronous notification
2691 * overlapped [In] overlapped structure that notifies the caller
2692 *
2693 * RETURNS
2694 * Success: NO_ERROR
2695 * Failure: error code from winerror.h
2696 *
2697 * FIXME
2698 * Stub, returns ERROR_NOT_SUPPORTED.
2699 */
2700 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
2701 {
2702 FIXME("(Handle %p, overlapped %p): stub\n", Handle, overlapped);
2703 return ERROR_NOT_SUPPORTED;
2704 }
2705
2706 /******************************************************************
2707 * SendARP (IPHLPAPI.@)
2708 *
2709 * Send an ARP request.
2710 *
2711 * PARAMS
2712 * DestIP [In] attempt to obtain this IP
2713 * SrcIP [In] optional sender IP address
2714 * pMacAddr [Out] buffer for the mac address
2715 * PhyAddrLen [In/Out] length of the output buffer
2716 *
2717 * RETURNS
2718 * Success: NO_ERROR
2719 * Failure: error code from winerror.h
2720 */
2721 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
2722 {
2723 IPAddr IPs[2];
2724 ULONG Size;
2725
2726 if (IsBadWritePtr(pMacAddr, sizeof(ULONG)) || IsBadWritePtr(PhyAddrLen, sizeof(ULONG)))
2727 return ERROR_INVALID_PARAMETER;
2728
2729 IPs[0] = DestIP;
2730 IPs[1] = SrcIP;
2731 Size = sizeof(IPs);
2732 return TCPSendIoctl(INVALID_HANDLE_VALUE, IOCTL_QUERY_IP_HW_ADDRESS, IPs, &Size, pMacAddr, PhyAddrLen);
2733 }
2734
2735
2736 /******************************************************************
2737 * SetIfEntry (IPHLPAPI.@)
2738 *
2739 * Set the administrative status of an interface.
2740 *
2741 * PARAMS
2742 * pIfRow [In] dwAdminStatus member specifies the new status.
2743 *
2744 * RETURNS
2745 * Success: NO_ERROR
2746 * Failure: error code from winerror.h
2747 *
2748 * FIXME
2749 * Stub, returns ERROR_NOT_SUPPORTED.
2750 */
2751 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
2752 {
2753 FIXME("(pIfRow %p): stub\n", pIfRow);
2754 /* this is supposed to set an interface administratively up or down.
2755 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
2756 this sort of down is indistinguishable from other sorts of down (e.g. no
2757 link). */
2758 return ERROR_NOT_SUPPORTED;
2759 }
2760
2761
2762 /******************************************************************
2763 * SetIpForwardEntry (IPHLPAPI.@)
2764 *
2765 * Modify an existing route.
2766 *
2767 * PARAMS
2768 * pRoute [In] route with the new information
2769 *
2770 * RETURNS
2771 * Success: NO_ERROR
2772 * Failure: error code from winerror.h
2773 *
2774 */
2775 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
2776 {
2777 return setIpForwardEntry( pRoute );
2778 }
2779
2780
2781 /******************************************************************
2782 * SetIpNetEntry (IPHLPAPI.@)
2783 *
2784 * Modify an existing ARP entry.
2785 *
2786 * PARAMS
2787 * pArpEntry [In] ARP entry with the new information
2788 *
2789 * RETURNS
2790 * Success: NO_ERROR
2791 * Failure: error code from winerror.h
2792 */
2793 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
2794 {
2795 HANDLE tcpFile;
2796 NTSTATUS status;
2797 TCP_REQUEST_SET_INFORMATION_EX_ARP_ENTRY req =
2798 TCP_REQUEST_SET_INFORMATION_INIT;
2799 TDIEntityID id;
2800 DWORD returnSize;
2801 PMIB_IPNETROW arpBuff;
2802
2803 if (!pArpEntry)
2804 return ERROR_INVALID_PARAMETER;
2805
2806 if (!NT_SUCCESS(openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA )))
2807 return ERROR_NOT_SUPPORTED;
2808
2809 if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id )))
2810 {
2811 closeTcpFile(tcpFile);
2812 return ERROR_INVALID_PARAMETER;
2813 }
2814
2815 req.Req.ID.toi_class = INFO_CLASS_PROTOCOL;
2816 req.Req.ID.toi_type = INFO_TYPE_PROVIDER;
2817 req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID;
2818 req.Req.ID.toi_entity.tei_instance = id.tei_instance;
2819 req.Req.ID.toi_entity.tei_entity = AT_ENTITY;
2820 req.Req.BufferSize = sizeof(MIB_IPNETROW);
2821 arpBuff = (PMIB_IPNETROW)&req.Req.Buffer[0];
2822
2823 RtlCopyMemory(arpBuff, pArpEntry, sizeof(MIB_IPNETROW));
2824
2825 status = DeviceIoControl( tcpFile,
2826 IOCTL_TCP_SET_INFORMATION_EX,
2827 &req,
2828 sizeof(req),
2829 NULL,
2830 0,
2831 &returnSize,
2832 NULL );
2833
2834 closeTcpFile(tcpFile);
2835
2836 if (status)
2837 return NO_ERROR;
2838 else
2839 return ERROR_INVALID_PARAMETER;
2840 }
2841
2842
2843 /******************************************************************
2844 * SetIpStatistics (IPHLPAPI.@)
2845 *
2846 * Toggle IP forwarding and det the default TTL value.
2847 *
2848 * PARAMS
2849 * pIpStats [In] IP statistics with the new information
2850 *
2851 * RETURNS
2852 * Success: NO_ERROR
2853 * Failure: error code from winerror.h
2854 *
2855 * FIXME
2856 * Stub, returns NO_ERROR.
2857 */
2858 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
2859 {
2860 FIXME("(pIpStats %p): stub\n", pIpStats);
2861 return 0;
2862 }
2863
2864
2865 /******************************************************************
2866 * SetIpTTL (IPHLPAPI.@)
2867 *
2868 * Set the default TTL value.
2869 *
2870 * PARAMS
2871 * nTTL [In] new TTL value
2872 *
2873 * RETURNS
2874 * Success: NO_ERROR
2875 * Failure: error code from winerror.h
2876 *
2877 * FIXME
2878 * Stub, returns NO_ERROR.
2879 */
2880 DWORD WINAPI SetIpTTL(UINT nTTL)
2881 {
2882 FIXME("(nTTL %d): stub\n", nTTL);
2883 return 0;
2884 }
2885
2886
2887 /******************************************************************
2888 * SetTcpEntry (IPHLPAPI.@)
2889 *
2890 * Set the state of a TCP connection.
2891 *
2892 * PARAMS
2893 * pTcpRow [In] specifies connection with new state
2894 *
2895 * RETURNS
2896 * Success: NO_ERROR
2897 * Failure: error code from winerror.h
2898 *
2899 * FIXME
2900 * Stub, returns NO_ERROR.
2901 */
2902 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
2903 {
2904 FIXME("(pTcpRow %p): stub\n", pTcpRow);
2905 return 0;
2906 }
2907
2908
2909 /******************************************************************
2910 * UnenableRouter (IPHLPAPI.@)
2911 *
2912 * Decrement the IP-forwarding reference count. Turn off IP-forwarding
2913 * if it reaches zero.
2914 *
2915 * PARAMS
2916 * pOverlapped [In/Out] should be the same as in EnableRouter()
2917 * lpdwEnableCount [Out] optional, receives reference count
2918 *
2919 * RETURNS
2920 * Success: NO_ERROR
2921 * Failure: error code from winerror.h
2922 *
2923 * FIXME
2924 * Stub, returns ERROR_NOT_SUPPORTED.
2925 */
2926 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
2927 {
2928 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped,
2929 lpdwEnableCount);
2930 return ERROR_NOT_SUPPORTED;
2931 }
2932
2933 /*
2934 * @unimplemented
2935 */
2936 DWORD WINAPI GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
2937 {
2938 FIXME(":stub\n");
2939 return 0L;
2940 }
2941
2942
2943 /*
2944 * @unimplemented
2945 */
2946 PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
2947 {
2948 FIXME(":stub\n");
2949 return 0L;
2950 }
2951
2952 /*
2953 * @implemented
2954 */
2955 #ifdef GetAdaptersAddressesV1
2956 DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
2957 {
2958 InterfaceIndexTable *indexTable;
2959 IFInfo ifInfo;
2960 int i;
2961 ULONG ret, requiredSize = 0;
2962 PIP_ADAPTER_ADDRESSES currentAddress;
2963 PUCHAR currentLocation;
2964 HANDLE tcpFile;
2965
2966 if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
2967 if (Reserved) return ERROR_INVALID_PARAMETER;
2968
2969 indexTable = getInterfaceIndexTable();
2970 if (!indexTable)
2971 return ERROR_NOT_ENOUGH_MEMORY;
2972
2973 ret = openTcpFile(&tcpFile, FILE_READ_DATA);
2974 if (!NT_SUCCESS(ret))
2975 return ERROR_NO_DATA;
2976
2977 for (i = indexTable->numIndexes; i >= 0; i--)
2978 {
2979 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
2980 NULL,
2981 indexTable->indexes[i],
2982 &ifInfo)))
2983 {
2984 /* The whole struct */
2985 requiredSize += sizeof(IP_ADAPTER_ADDRESSES);
2986
2987 /* Friendly name */
2988 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
2989 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1; //FIXME
2990
2991 /* Adapter name */
2992 requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
2993
2994 /* Unicast address */
2995 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
2996 requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
2997
2998 /* FIXME: Implement multicast, anycast, and dns server stuff */
2999
3000 /* FIXME: Implement dns suffix and description */
3001 requiredSize += 2 * sizeof(WCHAR);
3002
3003 /* We're only going to implement what's required for XP SP0 */
3004 }
3005 }
3006 TRACE("size: %d, requiredSize: %d\n", *pOutBufLen, requiredSize);
3007 if (!pAdapterAddresses || *pOutBufLen < requiredSize)
3008 {
3009 *pOutBufLen = requiredSize;
3010 closeTcpFile(tcpFile);
3011 free(indexTable);
3012 return ERROR_BUFFER_OVERFLOW;
3013 }
3014
3015 RtlZeroMemory(pAdapterAddresses, requiredSize);
3016
3017 /* Let's set up the pointers */
3018 currentAddress = pAdapterAddresses;
3019 for (i = indexTable->numIndexes; i >= 0; i--)
3020 {
3021 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
3022 NULL,
3023 indexTable->indexes[i],
3024 &ifInfo)))
3025 {
3026 currentLocation = (PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES);
3027
3028 /* FIXME: Friendly name */
3029 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
3030 {
3031 currentAddress->FriendlyName = (PVOID)currentLocation;
3032 currentLocation += sizeof(WCHAR);
3033 }
3034
3035 /* Adapter name */
3036 currentAddress->AdapterName = (PVOID)currentLocation;
3037 currentLocation += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
3038
3039 /* Unicast address */
3040 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
3041 {
3042 currentAddress->FirstUnicastAddress = (PVOID)currentLocation;
3043 currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
3044 currentAddress->FirstUnicastAddress->Address.lpSockaddr = (PVOID)currentLocation;
3045 currentLocation += sizeof(struct sockaddr);
3046 }
3047
3048 /* FIXME: Implement multicast, anycast, and dns server stuff */
3049
3050 /* FIXME: Implement dns suffix and description */
3051 currentAddress->DnsSuffix = (PVOID)currentLocation;
3052 currentLocation += sizeof(WCHAR);
3053
3054 currentAddress->Description = (PVOID)currentLocation;
3055 currentLocation += sizeof(WCHAR);
3056
3057 currentAddress->Next = (PVOID)currentLocation;
3058 /* Terminate the last address correctly */
3059 if(i==0)
3060 currentAddress->Next = NULL;
3061
3062 /* We're only going to implement what's required for XP SP0 */
3063
3064 currentAddress = currentAddress->Next;
3065 }
3066 }
3067
3068 /* Now again, for real this time */
3069
3070 currentAddress = pAdapterAddresses;
3071 for (i = indexTable->numIndexes; i >= 0; i--)
3072 {
3073 if (NT_SUCCESS(getIPAddrEntryForIf(tcpFile,
3074 NULL,
3075 indexTable->indexes[i],
3076 &ifInfo)))
3077 {
3078 /* Make sure we're not looping more than we hoped for */
3079 ASSERT(currentAddress);
3080
3081 /* Alignment information */
3082 currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES);
3083 currentAddress->IfIndex = indexTable->indexes[i];
3084
3085 /* Adapter name */
3086 strcpy(currentAddress->AdapterName, (char *)ifInfo.if_info.ent.if_descr);
3087
3088 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
3089 {
3090 currentAddress->FirstUnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
3091 currentAddress->FirstUnicastAddress->Flags = 0; //FIXME
3092 currentAddress->FirstUnicastAddress->Next = NULL; //FIXME: Support more than one address per adapter
3093 currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family = AF_INET;
3094 memcpy(currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data,
3095 &ifInfo.ip_addr.iae_addr,
3096 sizeof(ifInfo.ip_addr.iae_addr));
3097 currentAddress->FirstUnicastAddress->Address.iSockaddrLength = sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT);
3098 currentAddress->FirstUnicastAddress->PrefixOrigin = IpPrefixOriginOther; //FIXME
3099 currentAddress->FirstUnicastAddress->SuffixOrigin = IpPrefixOriginOther; //FIXME
3100 currentAddress->FirstUnicastAddress->DadState = IpDadStatePreferred; //FIXME
3101 currentAddress->FirstUnicastAddress->ValidLifetime = 0xFFFFFFFF; //FIXME
3102 currentAddress->FirstUnicastAddress->PreferredLifetime = 0xFFFFFFFF; //FIXME
3103 currentAddress->FirstUnicastAddress->LeaseLifetime = 0xFFFFFFFF; //FIXME
3104 }
3105
3106 /* FIXME: Implement multicast, anycast, and dns server stuff */
3107 currentAddress->FirstAnycastAddress = NULL;
3108 currentAddress->FirstMulticastAddress = NULL;
3109 currentAddress->FirstDnsServerAddress = NULL;
3110
3111 /* FIXME: Implement dns suffix, description, and friendly name */
3112 currentAddress->DnsSuffix[0] = UNICODE_NULL;
3113 currentAddress->Description[0] = UNICODE_NULL;
3114 currentAddress->FriendlyName[0] = UNICODE_NULL;
3115
3116 /* Physical Address */
3117 memcpy(currentAddress->PhysicalAddress, ifInfo.if_info.ent.if_physaddr, ifInfo.if_info.ent.if_physaddrlen);
3118 currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen;
3119
3120 /* Flags */
3121 currentAddress->Flags = 0; //FIXME
3122
3123 /* MTU */
3124 currentAddress->Mtu = ifInfo.if_info.ent.if_mtu;
3125
3126 /* Interface type */
3127 currentAddress->IfType = ifInfo.if_info.ent.if_type;
3128
3129 /* Operational status */
3130 if(ifInfo.if_info.ent.if_operstatus >= IF_OPER_STATUS_CONNECTING)
3131 currentAddress->OperStatus = IfOperStatusUp;
3132 else
3133 currentAddress->OperStatus = IfOperStatusDown;
3134
3135 /* We're only going to implement what's required for XP SP0 */
3136
3137 /* Move to the next address */
3138 currentAddress = currentAddress->Next;
3139 }
3140 }
3141
3142 closeTcpFile(tcpFile);
3143 free(indexTable);
3144
3145 return NO_ERROR;
3146 }
3147 #endif
3148
3149 /*
3150 * @unimplemented
3151 */
3152 BOOL WINAPI CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
3153 {
3154 FIXME(":stub\n");
3155 return 0L;
3156 }
3157
3158 /*
3159 * @unimplemented
3160 */
3161 DWORD WINAPI GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
3162 {
3163 FIXME(":stub\n");
3164 return 0L;
3165 }
3166
3167 /*
3168 * @unimplemented
3169 */
3170 DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
3171 {
3172 FIXME(":stub\n");
3173 return 0L;
3174 }
3175
3176 /*
3177 * @unimplemented
3178 */
3179 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
3180 {
3181 FIXME(":stub\n");
3182
3183 if (!pStats)
3184 return ERROR_INVALID_PARAMETER;
3185
3186 if (dwFamily != AF_INET && dwFamily != AF_INET6)
3187 return ERROR_INVALID_PARAMETER;
3188
3189 return 0L;
3190 }
3191
3192 DWORD WINAPI
3193 SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute)
3194 {
3195 FIXME("SetIpForwardEntryToStack() stub\n");
3196 return 0L;
3197 }
3198
3199 DWORD GetInterfaceNameInternal(_In_ const GUID * pInterfaceGUID,
3200 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
3201 _Inout_ PULONG pOutBufLen)
3202 {
3203 UNICODE_STRING GuidString;
3204 DWORD result, type;
3205 WCHAR szKeyName[2*MAX_PATH];
3206 HRESULT hr;
3207 HKEY hKey;
3208
3209 if (pInterfaceGUID == NULL || pOutBufLen == NULL)
3210 return ERROR_INVALID_PARAMETER;
3211
3212 result = RtlStringFromGUID(pInterfaceGUID, &GuidString);
3213
3214 if (!NT_SUCCESS(result))
3215 {
3216 // failed to convert guid to string
3217 return RtlNtStatusToDosError(result);
3218 }
3219
3220 hr = StringCbPrintfW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", GuidString.Buffer);
3221 RtlFreeUnicodeString(&GuidString);
3222
3223 if (FAILED(hr))
3224 {
3225 // key name is too long
3226 return ERROR_BUFFER_OVERFLOW;
3227 }
3228
3229 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKey);
3230
3231 if (result != ERROR_SUCCESS)
3232 {
3233 // failed to find adapter entry
3234 return ERROR_NOT_FOUND;
3235 }
3236
3237 result = RegQueryValueExW(hKey, L"Name", NULL, &type, (PVOID)pInterfaceName, pOutBufLen);
3238
3239 RegCloseKey(hKey);
3240
3241 if (result == ERROR_MORE_DATA)
3242 {
3243 *pOutBufLen = MAX_INTERFACE_NAME_LEN * 2;
3244 return ERROR_INSUFFICIENT_BUFFER;
3245 }
3246
3247 if (result != ERROR_SUCCESS || type != REG_SZ)
3248 {
3249 // failed to read adapter name
3250 return ERROR_NO_DATA;
3251 }
3252 return ERROR_SUCCESS;
3253 }
3254
3255 /*
3256 * @implemented
3257 */
3258 DWORD WINAPI
3259 NhGetInterfaceNameFromDeviceGuid(_In_ const GUID * pInterfaceGUID,
3260 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
3261 _Inout_ PULONG pOutBufLen,
3262 DWORD dwUnknown4,
3263 DWORD dwUnknown5)
3264 {
3265 SetLastError(ERROR_SUCCESS);
3266
3267 if (pInterfaceName == NULL)
3268 return ERROR_INVALID_PARAMETER;
3269
3270 return GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen);
3271 }
3272
3273 /*
3274 * @implemented
3275 */
3276 DWORD WINAPI
3277 NhGetInterfaceNameFromGuid(_In_ const GUID * pInterfaceGUID,
3278 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
3279 _Inout_ PULONG pOutBufLen,
3280 DWORD dwUnknown4,
3281 DWORD dwUnknown5)
3282 {
3283 DWORD result;
3284
3285 result = GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen);
3286
3287 if (result == ERROR_NOT_FOUND)
3288 SetLastError(ERROR_PATH_NOT_FOUND);
3289
3290 return result;
3291 }