Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / dll / win32 / iphlpapi / address.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/iphlpapi/address.c
5 * PURPOSE: iphlpapi implementation - Adapter Address APIs
6 * PROGRAMMERS: Jérôme Gardou (jerome.gardou@reactos.org)
7 */
8
9 #include "iphlpapi_private.h"
10
11 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
12 #ifdef GetAdaptersAddressesV2
13 /* Helper for GetAdaptersAddresses:
14 * Retrieves the list of network adapters from tcpip.sys */
15 static
16 NTSTATUS
17 GetInterfacesList(
18 _In_ HANDLE TcpFile,
19 _Out_ TDIEntityID **EntityList,
20 _Out_ ULONG* InterfaceCount)
21 {
22
23 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo;
24 IO_STATUS_BLOCK StatusBlock;
25 NTSTATUS Status;
26 ULONG_PTR BufferSize;
27
28 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo));
29 TcpQueryInfo.ID.toi_class = INFO_CLASS_GENERIC;
30 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER;
31 TcpQueryInfo.ID.toi_id = ENTITY_LIST_ID;
32 TcpQueryInfo.ID.toi_entity.tei_entity = GENERIC_ENTITY;
33 TcpQueryInfo.ID.toi_entity.tei_instance = 0;
34
35 Status = NtDeviceIoControlFile(
36 TcpFile,
37 NULL,
38 NULL,
39 NULL,
40 &StatusBlock,
41 IOCTL_TCP_QUERY_INFORMATION_EX,
42 &TcpQueryInfo,
43 sizeof(TcpQueryInfo),
44 NULL,
45 0);
46 if (Status == STATUS_PENDING)
47 {
48 /* So we have to wait a bit */
49 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
50 if (NT_SUCCESS(Status))
51 Status = StatusBlock.Status;
52 }
53
54 if (!NT_SUCCESS(Status))
55 return Status;
56
57 BufferSize = StatusBlock.Information;
58 *EntityList = HeapAlloc(GetProcessHeap(), 0, BufferSize);
59 if (!*EntityList)
60 return STATUS_NO_MEMORY;
61
62 /* Do the real call */
63 Status = NtDeviceIoControlFile(
64 TcpFile,
65 NULL,
66 NULL,
67 NULL,
68 &StatusBlock,
69 IOCTL_TCP_QUERY_INFORMATION_EX,
70 &TcpQueryInfo,
71 sizeof(TcpQueryInfo),
72 *EntityList,
73 BufferSize);
74 if (Status == STATUS_PENDING)
75 {
76 /* So we have to wait a bit */
77 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
78 if (NT_SUCCESS(Status))
79 Status = StatusBlock.Status;
80 }
81
82 if (!NT_SUCCESS(Status))
83 {
84 HeapFree(GetProcessHeap(), 0, *EntityList);
85 return Status;
86 }
87
88 *InterfaceCount = BufferSize / sizeof(TDIEntityID);
89 return Status;
90 }
91
92 static
93 NTSTATUS
94 GetSnmpInfo(
95 _In_ HANDLE TcpFile,
96 _In_ TDIEntityID InterfaceID,
97 _Out_ IPSNMPInfo* Info)
98 {
99 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo;
100 IO_STATUS_BLOCK StatusBlock;
101 NTSTATUS Status;
102
103 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo));
104 TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL;
105 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER;
106 TcpQueryInfo.ID.toi_id = IP_MIB_STATS_ID;
107 TcpQueryInfo.ID.toi_entity = InterfaceID;
108
109 Status = NtDeviceIoControlFile(
110 TcpFile,
111 NULL,
112 NULL,
113 NULL,
114 &StatusBlock,
115 IOCTL_TCP_QUERY_INFORMATION_EX,
116 &TcpQueryInfo,
117 sizeof(TcpQueryInfo),
118 Info,
119 sizeof(*Info));
120 if (Status == STATUS_PENDING)
121 {
122 /* So we have to wait a bit */
123 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
124 if (NT_SUCCESS(Status))
125 Status = StatusBlock.Status;
126 }
127
128 return Status;
129 }
130
131 static
132 NTSTATUS
133 GetAddrEntries(
134 _In_ HANDLE TcpFile,
135 _In_ TDIEntityID InterfaceID,
136 _Out_ IPAddrEntry* Entries,
137 _In_ ULONG NumEntries)
138 {
139 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo;
140 IO_STATUS_BLOCK StatusBlock;
141 NTSTATUS Status;
142
143 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo));
144 TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL;
145 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER;
146 TcpQueryInfo.ID.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
147 TcpQueryInfo.ID.toi_entity = InterfaceID;
148
149 Status = NtDeviceIoControlFile(
150 TcpFile,
151 NULL,
152 NULL,
153 NULL,
154 &StatusBlock,
155 IOCTL_TCP_QUERY_INFORMATION_EX,
156 &TcpQueryInfo,
157 sizeof(TcpQueryInfo),
158 Entries,
159 NumEntries * sizeof(Entries[0]));
160 if (Status == STATUS_PENDING)
161 {
162 /* So we have to wait a bit */
163 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
164 if (NT_SUCCESS(Status))
165 Status = StatusBlock.Status;
166 }
167
168 return Status;
169 }
170
171 /*
172 * Fills the IFEntry buffer from tcpip.sys.
173 * The buffer size MUST be FIELD_OFFSET(IFEntry, if_descr[MAX_ADAPTER_DESCRIPTION_LENGTH + 1]).
174 * See MSDN IFEntry struct definition if you don't believe me. ;-)
175 */
176 static
177 NTSTATUS
178 GetInterfaceEntry(
179 _In_ HANDLE TcpFile,
180 _In_ TDIEntityID InterfaceID,
181 _Out_ IFEntry* Entry)
182 {
183 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo;
184 IO_STATUS_BLOCK StatusBlock;
185 NTSTATUS Status;
186
187 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo));
188 TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL;
189 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER;
190 TcpQueryInfo.ID.toi_id = IP_MIB_STATS_ID;
191 TcpQueryInfo.ID.toi_entity = InterfaceID;
192
193 Status = NtDeviceIoControlFile(
194 TcpFile,
195 NULL,
196 NULL,
197 NULL,
198 &StatusBlock,
199 IOCTL_TCP_QUERY_INFORMATION_EX,
200 &TcpQueryInfo,
201 sizeof(TcpQueryInfo),
202 Entry,
203 FIELD_OFFSET(IFEntry, if_descr[MAX_ADAPTER_DESCRIPTION_LENGTH + 1]));
204 if (Status == STATUS_PENDING)
205 {
206 /* So we have to wait a bit */
207 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL);
208 if (NT_SUCCESS(Status))
209 Status = StatusBlock.Status;
210 }
211
212 return Status;
213 }
214
215 /* Helpers to get the list of DNS for an interface */
216 static
217 VOID
218 EnumerateServerNameSize(
219 _In_ PWCHAR Interface,
220 _In_ PWCHAR NameServer,
221 _Inout_ PVOID Data)
222 {
223 ULONG* BufferSize = Data;
224
225 /* This is just sizing here */
226 UNREFERENCED_PARAMETER(Interface);
227 UNREFERENCED_PARAMETER(NameServer);
228
229 *BufferSize += sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS) + sizeof(SOCKADDR);
230 }
231
232 static
233 VOID
234 EnumerateServerName(
235 _In_ PWCHAR Interface,
236 _In_ PWCHAR NameServer,
237 _Inout_ PVOID Data)
238 {
239 PIP_ADAPTER_DNS_SERVER_ADDRESS** Ptr = Data;
240 PIP_ADAPTER_DNS_SERVER_ADDRESS ServerAddress = **Ptr;
241
242 UNREFERENCED_PARAMETER(Interface);
243
244 ServerAddress->Length = sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS);
245 ServerAddress->Address.lpSockaddr = (PVOID)(ServerAddress + 1);
246 ServerAddress->Address.iSockaddrLength = sizeof(SOCKADDR);
247
248
249 /* Get the address from the server name string */
250 //FIXME: Only ipv4 for now...
251 if (WSAStringToAddressW(
252 NameServer,
253 AF_INET,
254 NULL,
255 ServerAddress->Address.lpSockaddr,
256 &ServerAddress->Address.iSockaddrLength))
257 {
258 /* Pass along, name conversion failed */
259 ERR("%S is not a valid IP address\n", NameServer);
260 return;
261 }
262
263 /* Go to next item */
264 ServerAddress->Next = (PVOID)(ServerAddress->Address.lpSockaddr + 1);
265 *Ptr = &ServerAddress->Next;
266 }
267
268 DWORD
269 WINAPI
270 DECLSPEC_HOTPATCH
271 GetAdaptersAddresses(
272 _In_ ULONG Family,
273 _In_ ULONG Flags,
274 _In_ PVOID Reserved,
275 _Inout_ PIP_ADAPTER_ADDRESSES pAdapterAddresses,
276 _Inout_ PULONG pOutBufLen)
277 {
278 NTSTATUS Status;
279 HANDLE TcpFile;
280 TDIEntityID* InterfacesList;
281 ULONG InterfacesCount;
282 ULONG AdaptersCount = 0;
283 ULONG i;
284 ULONG TotalSize = 0, RemainingSize;
285 BYTE* Ptr = (BYTE*)pAdapterAddresses;
286 DWORD MIN_SIZE = 15 * 1024;
287 PIP_ADAPTER_ADDRESSES PreviousAA = NULL;
288
289 FIXME("GetAdaptersAddresses - Semi Stub: Family %u, Flags 0x%08x, Reserved %p, pAdapterAddress %p, pOutBufLen %p.\n",
290 Family, Flags, Reserved, pAdapterAddresses, pOutBufLen);
291
292 if (!pOutBufLen)
293 return ERROR_INVALID_PARAMETER;
294
295 // FIXME: the exact needed size should be computed first, BEFORE doing any write to the output buffer.
296 // As suggested by MSDN, require a 15 KB buffer, which allows to React properly to length checks.
297 if(!Ptr || *pOutBufLen < MIN_SIZE)
298 {
299 *pOutBufLen = MIN_SIZE;
300 return ERROR_BUFFER_OVERFLOW;
301 }
302
303 switch(Family)
304 {
305 case AF_INET:
306 break;
307 case AF_INET6:
308 /* One day maybe... */
309 FIXME("IPv6 is not supported in ReactOS!\n");
310 /* We got nothing to say in this case */
311 return ERROR_NO_DATA;
312 break;
313 case AF_UNSPEC:
314 WARN("IPv6 addresses ignored, IPv4 only\n");
315 Family = AF_INET;
316 break;
317 default:
318 ERR("Invalid family 0x%x\n", Family);
319 return ERROR_INVALID_PARAMETER;
320 break;
321 }
322
323 RemainingSize = *pOutBufLen;
324 if (Ptr)
325 ZeroMemory(Ptr, RemainingSize);
326
327 /* open the tcpip driver */
328 Status = openTcpFile(&TcpFile, FILE_READ_DATA);
329 if (!NT_SUCCESS(Status))
330 {
331 ERR("Could not open handle to tcpip.sys. Status %08x\n", Status);
332 return RtlNtStatusToDosError(Status);
333 }
334
335 /* Get the interfaces list */
336 Status = GetInterfacesList(TcpFile, &InterfacesList, &InterfacesCount);
337 if (!NT_SUCCESS(Status))
338 {
339 ERR("Could not get adapters list. Status %08x\n", Status);
340 NtClose(TcpFile);
341 return RtlNtStatusToDosError(Status);
342 }
343
344 /* Let's see if we got any adapter. */
345 for (i = 0; i < InterfacesCount; i++)
346 {
347 PIP_ADAPTER_ADDRESSES CurrentAA = (PIP_ADAPTER_ADDRESSES)Ptr;
348 ULONG CurrentAASize = 0;
349
350 if (InterfacesList[i].tei_entity == IF_ENTITY)
351 {
352 BYTE EntryBuffer[FIELD_OFFSET(IFEntry, if_descr) +
353 RTL_FIELD_SIZE(IFEntry, if_descr[0]) * (MAX_ADAPTER_DESCRIPTION_LENGTH + 1)];
354 IFEntry* Entry = (IFEntry*)EntryBuffer;
355
356 /* Remember we got one */
357 AdaptersCount++;
358
359 /* Set the pointer to this instance in the previous one*/
360 if(PreviousAA)
361 PreviousAA->Next = CurrentAA;
362
363 /* Of course we need some space for the base structure. */
364 CurrentAASize = sizeof(IP_ADAPTER_ADDRESSES);
365
366 /* Get the entry */
367 Status = GetInterfaceEntry(TcpFile, InterfacesList[i], Entry);
368 if (!NT_SUCCESS(Status))
369 goto Error;
370
371 TRACE("Got entity %*s, index %u.\n",
372 Entry->if_descrlen, &Entry->if_descr[0], Entry->if_index);
373
374 /* Add the adapter name */
375 CurrentAASize += Entry->if_descrlen + sizeof(CHAR);
376
377 /* Add the DNS suffix */
378 CurrentAASize += sizeof(WCHAR);
379
380 /* Add the description. */
381 CurrentAASize += sizeof(WCHAR);
382
383 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
384 {
385 /* Just an empty string for now. */
386 FIXME("Should get adapter friendly name.\n");
387 CurrentAASize += sizeof(WCHAR);
388 }
389
390 if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER))
391 {
392 /* Enumerate the name servers */
393 HKEY InterfaceKey;
394 CHAR KeyName[256];
395
396 snprintf(KeyName, 256,
397 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
398 Entry->if_descrlen, &Entry->if_descr[0]);
399
400 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) == ERROR_SUCCESS)
401 {
402 EnumNameServers(InterfaceKey, NULL, &CurrentAASize, EnumerateServerNameSize);
403 RegCloseKey(InterfaceKey);
404 }
405 }
406
407 /* This is part of what we will need */
408 TotalSize += CurrentAASize;
409
410 /* Fill in the data */
411 if ((CurrentAA) && (RemainingSize >= CurrentAASize))
412 {
413 CurrentAA->Length = sizeof(IP_ADAPTER_ADDRESSES);
414 CurrentAA->IfIndex = Entry->if_index;
415 CopyMemory(CurrentAA->PhysicalAddress, Entry->if_physaddr, Entry->if_physaddrlen);
416 CurrentAA->PhysicalAddressLength = Entry->if_physaddrlen;
417 CurrentAA->Flags = 0; // FIXME!
418 CurrentAA->Mtu = Entry->if_mtu;
419 CurrentAA->IfType = Entry->if_type;
420 if(Entry->if_operstatus >= IF_OPER_STATUS_CONNECTING)
421 CurrentAA->OperStatus = IfOperStatusUp;
422 else
423 CurrentAA->OperStatus = IfOperStatusDown;
424
425 /* Next items */
426 Ptr = (BYTE*)(CurrentAA + 1);
427
428 /* Now fill in the name */
429 CopyMemory(Ptr, &Entry->if_descr[0], Entry->if_descrlen);
430 CurrentAA->AdapterName = (PCHAR)Ptr;
431 CurrentAA->AdapterName[Entry->if_descrlen] = '\0';
432 /* Next items */
433 Ptr = (BYTE*)(CurrentAA->AdapterName + Entry->if_descrlen + 1);
434
435 /* The DNS suffix */
436 CurrentAA->DnsSuffix = (PWCHAR)Ptr;
437 CurrentAA->DnsSuffix[0] = L'\0';
438 /* Next items */
439 Ptr = (BYTE*)(CurrentAA->DnsSuffix + 1);
440
441 /* The description */
442 CurrentAA->Description = (PWCHAR)Ptr;
443 CurrentAA->Description[0] = L'\0';
444 /* Next items */
445 Ptr = (BYTE*)(CurrentAA->Description + 1);
446
447 /* The friendly name */
448 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
449 {
450 CurrentAA->FriendlyName = (PWCHAR)Ptr;
451 CurrentAA->FriendlyName[0] = L'\0';
452 /* Next items */
453 Ptr = (BYTE*)(CurrentAA->FriendlyName + 1);
454 }
455
456 /* The DNS Servers */
457 if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER))
458 {
459 /* Enumerate the name servers */
460 HKEY InterfaceKey;
461 CHAR KeyName[256];
462
463 snprintf(KeyName, 256,
464 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
465 Entry->if_descrlen, &Entry->if_descr[0]);
466
467 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) != ERROR_SUCCESS)
468 {
469 TRACE("Failed opening interface key for interface %*s\n", Entry->if_descrlen, &Entry->if_descr[0]);
470 }
471 else
472 {
473 PIP_ADAPTER_DNS_SERVER_ADDRESS* ServerAddressPtr;
474
475 CurrentAA->FirstDnsServerAddress = (PIP_ADAPTER_DNS_SERVER_ADDRESS)Ptr;
476 ServerAddressPtr = &CurrentAA->FirstDnsServerAddress;
477
478 EnumNameServers(InterfaceKey, NULL, &ServerAddressPtr, EnumerateServerName);
479 RegCloseKey(InterfaceKey);
480
481 /* Set the last entry in the list as having NULL next member */
482 Ptr = (BYTE*)*ServerAddressPtr;
483 *ServerAddressPtr = NULL;
484 }
485 }
486
487 /* We're done for this interface */
488 PreviousAA = CurrentAA;
489 RemainingSize -= CurrentAASize;
490 }
491 }
492 }
493
494 if (AdaptersCount == 0)
495 {
496 /* Uh? Not even localhost ?! */
497 ERR("No Adapters found!\n");
498 *pOutBufLen = 0;
499 return ERROR_NO_DATA;
500 }
501
502 /* See if we have anything to add */
503 // FIXME: Anycast and multicast
504 if ((Flags & (GAA_FLAG_SKIP_UNICAST | GAA_FLAG_INCLUDE_PREFIX)) == GAA_FLAG_SKIP_UNICAST)
505 goto Success;
506
507 /* Now fill in the addresses */
508 for (i = 0; i < InterfacesCount; i++)
509 {
510 /* Look for network layers */
511 if ((InterfacesList[i].tei_entity == CL_NL_ENTITY)
512 || (InterfacesList[i].tei_entity == CO_NL_ENTITY))
513 {
514 IPSNMPInfo SnmpInfo;
515 PIP_ADAPTER_ADDRESSES CurrentAA = NULL;
516 IPAddrEntry* AddrEntries;
517 ULONG j;
518
519 /* Get its SNMP info */
520 Status = GetSnmpInfo(TcpFile, InterfacesList[i], &SnmpInfo);
521 if (!NT_SUCCESS(Status))
522 goto Error;
523
524 if (SnmpInfo.ipsi_numaddr == 0)
525 continue;
526
527 /* Allocate the address entry array and get them */
528 AddrEntries = HeapAlloc(GetProcessHeap(),
529 HEAP_ZERO_MEMORY,
530 SnmpInfo.ipsi_numaddr * sizeof(AddrEntries[0]));
531 if (!AddrEntries)
532 {
533 Status = STATUS_NO_MEMORY;
534 goto Error;
535 }
536 Status = GetAddrEntries(TcpFile, InterfacesList[i], AddrEntries, SnmpInfo.ipsi_numaddr);
537 if (!NT_SUCCESS(Status))
538 {
539 HeapFree(GetProcessHeap(), 0, AddrEntries);
540 goto Error;
541 }
542
543 for (j = 0; j < SnmpInfo.ipsi_numaddr; j++)
544 {
545 /* Find the adapters struct for this address. */
546 if (pAdapterAddresses)
547 {
548 CurrentAA = pAdapterAddresses;
549 while (CurrentAA)
550 {
551 if (CurrentAA->IfIndex == AddrEntries[j].iae_index)
552 break;
553
554 CurrentAA = CurrentAA->Next;
555 }
556
557 if (!CurrentAA)
558 {
559 ERR("Got address for interface %u but no adapter was found for it.\n", AddrEntries[j].iae_index);
560 /* Go to the next address */
561 continue;
562 }
563 }
564
565 TRACE("address is 0x%08x, mask is 0x%08x\n", AddrEntries[j].iae_addr, AddrEntries[j].iae_mask);
566
567 //FIXME: For now reactos only supports unicast addresses
568 if (!(Flags & GAA_FLAG_SKIP_UNICAST))
569 {
570 ULONG Size = sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR);
571
572 if (Ptr && (RemainingSize >= Size))
573 {
574 PIP_ADAPTER_UNICAST_ADDRESS UnicastAddress = (PIP_ADAPTER_UNICAST_ADDRESS)Ptr;
575
576 /* Fill in the structure */
577 UnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
578 UnicastAddress->Next = CurrentAA->FirstUnicastAddress;
579
580 // FIXME: Put meaningful value here
581 UnicastAddress->Flags = 0;
582 UnicastAddress->PrefixOrigin = IpPrefixOriginOther;
583 UnicastAddress->SuffixOrigin = IpSuffixOriginOther;
584 UnicastAddress->DadState = IpDadStatePreferred;
585 UnicastAddress->ValidLifetime = 0xFFFFFFFF;
586 UnicastAddress->PreferredLifetime = 0xFFFFFFFF;
587
588 /* Set the address */
589 //FIXME: ipv4 only (again...)
590 UnicastAddress->Address.lpSockaddr = (LPSOCKADDR)(UnicastAddress + 1);
591 UnicastAddress->Address.iSockaddrLength = sizeof(SOCKADDR);
592 UnicastAddress->Address.lpSockaddr->sa_family = AF_INET;
593 ((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_port = 0;
594 memcpy(&((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_addr, &AddrEntries[j].iae_addr, sizeof(AddrEntries[j].iae_addr));
595
596 CurrentAA->FirstUnicastAddress = UnicastAddress;
597 Ptr += Size;
598 RemainingSize -= Size;
599 }
600
601 TotalSize += Size;
602 }
603
604 if (Flags & GAA_FLAG_INCLUDE_PREFIX)
605 {
606 ULONG Size = sizeof(IP_ADAPTER_PREFIX) + sizeof(SOCKADDR);
607
608 if (Ptr && (RemainingSize >= Size))
609 {
610 PIP_ADAPTER_PREFIX Prefix = (PIP_ADAPTER_PREFIX)Ptr;
611
612 /* Fill in the structure */
613 Prefix->Length = sizeof(IP_ADAPTER_PREFIX);
614 Prefix->Next = CurrentAA->FirstPrefix;
615
616 /* Set the address */
617 //FIXME: ipv4 only (again...)
618 Prefix->Address.lpSockaddr = (LPSOCKADDR)(Prefix + 1);
619 Prefix->Address.iSockaddrLength = sizeof(AddrEntries[j].iae_mask);
620 Prefix->Address.lpSockaddr->sa_family = AF_INET;
621 memcpy(Prefix->Address.lpSockaddr->sa_data, &AddrEntries[j].iae_mask, sizeof(AddrEntries[j].iae_mask));
622
623 /* Compute the prefix size */
624 _BitScanReverse(&Prefix->PrefixLength, AddrEntries[j].iae_mask);
625
626 CurrentAA->FirstPrefix = Prefix;
627 Ptr += Size;
628 RemainingSize -= Size;
629 }
630
631 TotalSize += Size;
632 }
633 }
634
635 HeapFree(GetProcessHeap(), 0, AddrEntries);
636 }
637 }
638
639 Success:
640 /* We're done */
641 HeapFree(GetProcessHeap(), 0, InterfacesList);
642 NtClose(TcpFile);
643 *pOutBufLen = TotalSize;
644 TRACE("TotalSize: %x\n", *pOutBufLen);
645 return ERROR_SUCCESS;
646
647 Error:
648 ERR("Failed! Status 0x%08x\n", Status);
649 *pOutBufLen = 0;
650 HeapFree(GetProcessHeap(), 0, InterfacesList);
651 NtClose(TcpFile);
652 return RtlNtStatusToDosError(Status);
653 }
654 #endif