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