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)
9 #include "iphlpapi_private.h"
11 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi
);
12 #ifdef GetAdaptersAddressesV2
13 /* Helper for GetAdaptersAddresses:
14 * Retrieves the list of network adapters from tcpip.sys */
19 _Out_ TDIEntityID
**EntityList
,
20 _Out_ ULONG
* InterfaceCount
)
23 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo
;
24 IO_STATUS_BLOCK StatusBlock
;
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;
35 Status
= NtDeviceIoControlFile(
41 IOCTL_TCP_QUERY_INFORMATION_EX
,
46 if (Status
== STATUS_PENDING
)
48 /* So we have to wait a bit */
49 Status
= NtWaitForSingleObject(TcpFile
, FALSE
, NULL
);
50 if (NT_SUCCESS(Status
))
51 Status
= StatusBlock
.Status
;
54 if (!NT_SUCCESS(Status
))
57 BufferSize
= StatusBlock
.Information
;
58 *EntityList
= HeapAlloc(GetProcessHeap(), 0, BufferSize
);
60 return STATUS_NO_MEMORY
;
62 /* Do the real call */
63 Status
= NtDeviceIoControlFile(
69 IOCTL_TCP_QUERY_INFORMATION_EX
,
74 if (Status
== STATUS_PENDING
)
76 /* So we have to wait a bit */
77 Status
= NtWaitForSingleObject(TcpFile
, FALSE
, NULL
);
78 if (NT_SUCCESS(Status
))
79 Status
= StatusBlock
.Status
;
82 if (!NT_SUCCESS(Status
))
84 HeapFree(GetProcessHeap(), 0, *EntityList
);
88 *InterfaceCount
= BufferSize
/ sizeof(TDIEntityID
);
96 _In_ TDIEntityID InterfaceID
,
97 _Out_ IPSNMPInfo
* Info
)
99 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo
;
100 IO_STATUS_BLOCK StatusBlock
;
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
;
109 Status
= NtDeviceIoControlFile(
115 IOCTL_TCP_QUERY_INFORMATION_EX
,
117 sizeof(TcpQueryInfo
),
120 if (Status
== STATUS_PENDING
)
122 /* So we have to wait a bit */
123 Status
= NtWaitForSingleObject(TcpFile
, FALSE
, NULL
);
124 if (NT_SUCCESS(Status
))
125 Status
= StatusBlock
.Status
;
135 _In_ TDIEntityID InterfaceID
,
136 _Out_ IPAddrEntry
* Entries
,
137 _In_ ULONG NumEntries
)
139 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo
;
140 IO_STATUS_BLOCK StatusBlock
;
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
;
149 Status
= NtDeviceIoControlFile(
155 IOCTL_TCP_QUERY_INFORMATION_EX
,
157 sizeof(TcpQueryInfo
),
159 NumEntries
* sizeof(Entries
[0]));
160 if (Status
== STATUS_PENDING
)
162 /* So we have to wait a bit */
163 Status
= NtWaitForSingleObject(TcpFile
, FALSE
, NULL
);
164 if (NT_SUCCESS(Status
))
165 Status
= StatusBlock
.Status
;
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. ;-)
180 _In_ TDIEntityID InterfaceID
,
181 _Out_ IFEntry
* Entry
)
183 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo
;
184 IO_STATUS_BLOCK StatusBlock
;
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
;
193 Status
= NtDeviceIoControlFile(
199 IOCTL_TCP_QUERY_INFORMATION_EX
,
201 sizeof(TcpQueryInfo
),
203 FIELD_OFFSET(IFEntry
, if_descr
[MAX_ADAPTER_DESCRIPTION_LENGTH
+ 1]));
204 if (Status
== STATUS_PENDING
)
206 /* So we have to wait a bit */
207 Status
= NtWaitForSingleObject(TcpFile
, FALSE
, NULL
);
208 if (NT_SUCCESS(Status
))
209 Status
= StatusBlock
.Status
;
215 /* Helpers to get the list of DNS for an interface */
218 EnumerateServerNameSize(
219 _In_ PWCHAR Interface
,
220 _In_ PWCHAR NameServer
,
223 ULONG
* BufferSize
= Data
;
225 /* This is just sizing here */
226 UNREFERENCED_PARAMETER(Interface
);
227 UNREFERENCED_PARAMETER(NameServer
);
229 *BufferSize
+= sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS
) + sizeof(SOCKADDR
);
235 _In_ PWCHAR Interface
,
236 _In_ PWCHAR NameServer
,
239 PIP_ADAPTER_DNS_SERVER_ADDRESS
** Ptr
= Data
;
240 PIP_ADAPTER_DNS_SERVER_ADDRESS ServerAddress
= **Ptr
;
242 UNREFERENCED_PARAMETER(Interface
);
244 ServerAddress
->Length
= sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS
);
245 ServerAddress
->Address
.lpSockaddr
= (PVOID
)(ServerAddress
+ 1);
246 ServerAddress
->Address
.iSockaddrLength
= sizeof(SOCKADDR
);
249 /* Get the address from the server name string */
250 //FIXME: Only ipv4 for now...
251 if (WSAStringToAddressW(
255 ServerAddress
->Address
.lpSockaddr
,
256 &ServerAddress
->Address
.iSockaddrLength
))
258 /* Pass along, name conversion failed */
259 ERR("%S is not a valid IP address\n", NameServer
);
263 /* Go to next item */
264 ServerAddress
->Next
= (PVOID
)(ServerAddress
->Address
.lpSockaddr
+ 1);
265 *Ptr
= &ServerAddress
->Next
;
271 _In_ PUCHAR Interface
,
272 _In_ DWORD InterfaceLength
,
277 DWORD Type
, Size
, Data
;
281 snprintf(KeyName
, 256,
282 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
283 InterfaceLength
, Interface
);
285 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, KeyName
, 0, KEY_READ
, &InterfaceKey
) == ERROR_SUCCESS
)
287 Size
= sizeof(DWORD
);
288 if (RegQueryValueExA(InterfaceKey
, "EnableDHCP", NULL
, &Type
, (LPBYTE
)&Data
, &Size
) == ERROR_SUCCESS
&&
289 Type
== REG_DWORD
&& Data
== 1)
291 *Flags
|= IP_ADAPTER_DHCP_ENABLED
;
294 Size
= sizeof(DWORD
);
295 if (RegQueryValueExA(InterfaceKey
, "RegisterAdapterName", NULL
, &Type
, (LPBYTE
)&Data
, &Size
) == ERROR_SUCCESS
&&
296 Type
== REG_DWORD
&& Data
== 1)
298 *Flags
|= IP_ADAPTER_REGISTER_ADAPTER_SUFFIX
;
302 if (RegQueryValueExA(InterfaceKey
, "NameServer", NULL
, &Type
, (LPBYTE
)&Data
, &Size
) != ERROR_SUCCESS
)
304 *Flags
|= IP_ADAPTER_DDNS_ENABLED
;
307 RegCloseKey(InterfaceKey
);
310 // FIXME: handle 0x8 -> 0x20
316 GetAdaptersAddresses(
320 _Inout_ PIP_ADAPTER_ADDRESSES pAdapterAddresses
,
321 _Inout_ PULONG pOutBufLen
)
325 TDIEntityID
* InterfacesList
;
326 ULONG InterfacesCount
;
327 ULONG AdaptersCount
= 0;
329 ULONG TotalSize
= 0, RemainingSize
;
330 BYTE
* Ptr
= (BYTE
*)pAdapterAddresses
;
331 DWORD MIN_SIZE
= 15 * 1024;
332 PIP_ADAPTER_ADDRESSES PreviousAA
= NULL
;
334 FIXME("GetAdaptersAddresses - Semi Stub: Family %u, Flags 0x%08x, Reserved %p, pAdapterAddress %p, pOutBufLen %p.\n",
335 Family
, Flags
, Reserved
, pAdapterAddresses
, pOutBufLen
);
338 return ERROR_INVALID_PARAMETER
;
340 // FIXME: the exact needed size should be computed first, BEFORE doing any write to the output buffer.
341 // As suggested by MSDN, require a 15 KB buffer, which allows to React properly to length checks.
342 if(!Ptr
|| *pOutBufLen
< MIN_SIZE
)
344 *pOutBufLen
= MIN_SIZE
;
345 return ERROR_BUFFER_OVERFLOW
;
353 /* One day maybe... */
354 FIXME("IPv6 is not supported in ReactOS!\n");
355 /* We got nothing to say in this case */
356 return ERROR_NO_DATA
;
359 WARN("IPv6 addresses ignored, IPv4 only\n");
363 ERR("Invalid family 0x%x\n", Family
);
364 return ERROR_INVALID_PARAMETER
;
368 RemainingSize
= *pOutBufLen
;
370 ZeroMemory(Ptr
, RemainingSize
);
372 /* open the tcpip driver */
373 Status
= openTcpFile(&TcpFile
, FILE_READ_DATA
);
374 if (!NT_SUCCESS(Status
))
376 ERR("Could not open handle to tcpip.sys. Status %08x\n", Status
);
377 return RtlNtStatusToDosError(Status
);
380 /* Get the interfaces list */
381 Status
= GetInterfacesList(TcpFile
, &InterfacesList
, &InterfacesCount
);
382 if (!NT_SUCCESS(Status
))
384 ERR("Could not get adapters list. Status %08x\n", Status
);
386 return RtlNtStatusToDosError(Status
);
389 /* Let's see if we got any adapter. */
390 for (i
= 0; i
< InterfacesCount
; i
++)
392 PIP_ADAPTER_ADDRESSES CurrentAA
= (PIP_ADAPTER_ADDRESSES
)Ptr
;
393 ULONG CurrentAASize
= 0;
394 ULONG FriendlySize
= 0;
396 if (InterfacesList
[i
].tei_entity
== IF_ENTITY
)
398 BYTE EntryBuffer
[FIELD_OFFSET(IFEntry
, if_descr
) +
399 RTL_FIELD_SIZE(IFEntry
, if_descr
[0]) * (MAX_ADAPTER_DESCRIPTION_LENGTH
+ 1)];
400 IFEntry
* Entry
= (IFEntry
*)EntryBuffer
;
402 /* Remember we got one */
405 /* Set the pointer to this instance in the previous one*/
407 PreviousAA
->Next
= CurrentAA
;
409 /* Of course we need some space for the base structure. */
410 CurrentAASize
= sizeof(IP_ADAPTER_ADDRESSES
);
413 Status
= GetInterfaceEntry(TcpFile
, InterfacesList
[i
], Entry
);
414 if (!NT_SUCCESS(Status
))
417 TRACE("Got entity %*s, index %u.\n",
418 Entry
->if_descrlen
, &Entry
->if_descr
[0], Entry
->if_index
);
420 /* Add the adapter name */
421 CurrentAASize
+= Entry
->if_descrlen
+ sizeof(CHAR
);
423 /* Add the DNS suffix */
424 CurrentAASize
+= sizeof(WCHAR
);
426 /* Add the description. */
427 CurrentAASize
+= sizeof(WCHAR
);
429 if (!(Flags
& GAA_FLAG_SKIP_FRIENDLY_NAME
))
431 /* Get the friendly name */
435 snprintf(KeyName
, 256,
436 "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%*s\\Connection",
437 Entry
->if_descrlen
, &Entry
->if_descr
[0]);
439 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, KeyName
, 0, KEY_READ
, &ConnectionKey
) == ERROR_SUCCESS
)
444 if (RegQueryValueExW(ConnectionKey
, L
"Name", NULL
, &ValueType
, NULL
, &ValueSize
) == ERROR_SUCCESS
&&
447 /* We remove the null char, it will be re-added after */
448 FriendlySize
= ValueSize
- sizeof(WCHAR
);
449 CurrentAASize
+= FriendlySize
;
452 RegCloseKey(ConnectionKey
);
455 /* We always make sure to have enough room for empty string */
456 CurrentAASize
+= sizeof(WCHAR
);
459 if (!(Flags
& GAA_FLAG_SKIP_DNS_SERVER
))
461 /* Enumerate the name servers */
465 snprintf(KeyName
, 256,
466 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
467 Entry
->if_descrlen
, &Entry
->if_descr
[0]);
469 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, KeyName
, 0, KEY_READ
, &InterfaceKey
) == ERROR_SUCCESS
)
471 EnumNameServers(InterfaceKey
, NULL
, &CurrentAASize
, EnumerateServerNameSize
);
472 RegCloseKey(InterfaceKey
);
476 /* This is part of what we will need */
477 TotalSize
+= CurrentAASize
;
479 /* Fill in the data */
480 if ((CurrentAA
) && (RemainingSize
>= CurrentAASize
))
482 CurrentAA
->Length
= sizeof(IP_ADAPTER_ADDRESSES
);
483 CurrentAA
->IfIndex
= Entry
->if_index
;
484 CopyMemory(CurrentAA
->PhysicalAddress
, Entry
->if_physaddr
, Entry
->if_physaddrlen
);
485 CurrentAA
->PhysicalAddressLength
= Entry
->if_physaddrlen
;
486 QueryFlags(&Entry
->if_descr
[0], Entry
->if_descrlen
, &CurrentAA
->Flags
);
487 CurrentAA
->Mtu
= Entry
->if_mtu
;
488 CurrentAA
->IfType
= Entry
->if_type
;
489 if(Entry
->if_operstatus
>= IF_OPER_STATUS_CONNECTING
)
490 CurrentAA
->OperStatus
= IfOperStatusUp
;
492 CurrentAA
->OperStatus
= IfOperStatusDown
;
495 Ptr
= (BYTE
*)(CurrentAA
+ 1);
497 /* Now fill in the name */
498 CopyMemory(Ptr
, &Entry
->if_descr
[0], Entry
->if_descrlen
);
499 CurrentAA
->AdapterName
= (PCHAR
)Ptr
;
500 CurrentAA
->AdapterName
[Entry
->if_descrlen
] = '\0';
502 Ptr
= (BYTE
*)(CurrentAA
->AdapterName
+ Entry
->if_descrlen
+ 1);
505 CurrentAA
->DnsSuffix
= (PWCHAR
)Ptr
;
506 CurrentAA
->DnsSuffix
[0] = L
'\0';
508 Ptr
= (BYTE
*)(CurrentAA
->DnsSuffix
+ 1);
510 /* The description */
511 CurrentAA
->Description
= (PWCHAR
)Ptr
;
512 CurrentAA
->Description
[0] = L
'\0';
514 Ptr
= (BYTE
*)(CurrentAA
->Description
+ 1);
516 /* The friendly name */
517 if (!(Flags
& GAA_FLAG_SKIP_FRIENDLY_NAME
))
519 CurrentAA
->FriendlyName
= (PWCHAR
)Ptr
;
521 if (FriendlySize
!= 0)
523 /* Get the friendly name */
527 snprintf(KeyName
, 256,
528 "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%*s\\Connection",
529 Entry
->if_descrlen
, &Entry
->if_descr
[0]);
531 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, KeyName
, 0, KEY_READ
, &ConnectionKey
) == ERROR_SUCCESS
)
534 DWORD ValueSize
= FriendlySize
+ sizeof(WCHAR
);
536 if (RegQueryValueExW(ConnectionKey
, L
"Name", NULL
, &ValueType
, (LPBYTE
)CurrentAA
->FriendlyName
, &ValueSize
) == ERROR_SUCCESS
&&
537 ValueType
== REG_SZ
&& ValueSize
== FriendlySize
+ sizeof(WCHAR
))
539 /* We're done, next items */
540 Ptr
= (BYTE
*)(CurrentAA
->FriendlyName
+ (ValueSize
/ sizeof(WCHAR
)));
545 ERR("Friendly name changed after probe!\n");
549 RegCloseKey(ConnectionKey
);
558 /* In case of failure (or no name) */
559 if (FriendlySize
== 0)
561 CurrentAA
->FriendlyName
[0] = L
'\0';
563 Ptr
= (BYTE
*)(CurrentAA
->FriendlyName
+ 1);
567 /* The DNS Servers */
568 if (!(Flags
& GAA_FLAG_SKIP_DNS_SERVER
))
570 /* Enumerate the name servers */
574 snprintf(KeyName
, 256,
575 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s",
576 Entry
->if_descrlen
, &Entry
->if_descr
[0]);
578 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, KeyName
, 0, KEY_READ
, &InterfaceKey
) != ERROR_SUCCESS
)
580 TRACE("Failed opening interface key for interface %*s\n", Entry
->if_descrlen
, &Entry
->if_descr
[0]);
584 PIP_ADAPTER_DNS_SERVER_ADDRESS
* ServerAddressPtr
;
586 CurrentAA
->FirstDnsServerAddress
= (PIP_ADAPTER_DNS_SERVER_ADDRESS
)Ptr
;
587 ServerAddressPtr
= &CurrentAA
->FirstDnsServerAddress
;
589 EnumNameServers(InterfaceKey
, NULL
, &ServerAddressPtr
, EnumerateServerName
);
590 RegCloseKey(InterfaceKey
);
592 /* Set the last entry in the list as having NULL next member */
593 Ptr
= (BYTE
*)*ServerAddressPtr
;
594 *ServerAddressPtr
= NULL
;
598 /* We're done for this interface */
599 PreviousAA
= CurrentAA
;
600 RemainingSize
-= CurrentAASize
;
605 if (AdaptersCount
== 0)
607 /* Uh? Not even localhost ?! */
608 ERR("No Adapters found!\n");
610 return ERROR_NO_DATA
;
613 /* See if we have anything to add */
614 // FIXME: Anycast and multicast
615 if ((Flags
& (GAA_FLAG_SKIP_UNICAST
| GAA_FLAG_INCLUDE_PREFIX
)) == GAA_FLAG_SKIP_UNICAST
)
618 /* Now fill in the addresses */
619 for (i
= 0; i
< InterfacesCount
; i
++)
621 /* Look for network layers */
622 if ((InterfacesList
[i
].tei_entity
== CL_NL_ENTITY
)
623 || (InterfacesList
[i
].tei_entity
== CO_NL_ENTITY
))
626 PIP_ADAPTER_ADDRESSES CurrentAA
= NULL
;
627 IPAddrEntry
* AddrEntries
;
630 /* Get its SNMP info */
631 Status
= GetSnmpInfo(TcpFile
, InterfacesList
[i
], &SnmpInfo
);
632 if (!NT_SUCCESS(Status
))
635 if (SnmpInfo
.ipsi_numaddr
== 0)
638 /* Allocate the address entry array and get them */
639 AddrEntries
= HeapAlloc(GetProcessHeap(),
641 SnmpInfo
.ipsi_numaddr
* sizeof(AddrEntries
[0]));
644 Status
= STATUS_NO_MEMORY
;
647 Status
= GetAddrEntries(TcpFile
, InterfacesList
[i
], AddrEntries
, SnmpInfo
.ipsi_numaddr
);
648 if (!NT_SUCCESS(Status
))
650 HeapFree(GetProcessHeap(), 0, AddrEntries
);
654 for (j
= 0; j
< SnmpInfo
.ipsi_numaddr
; j
++)
656 /* Find the adapters struct for this address. */
657 if (pAdapterAddresses
)
659 CurrentAA
= pAdapterAddresses
;
662 if (CurrentAA
->IfIndex
== AddrEntries
[j
].iae_index
)
665 CurrentAA
= CurrentAA
->Next
;
670 ERR("Got address for interface %u but no adapter was found for it.\n", AddrEntries
[j
].iae_index
);
671 /* Go to the next address */
676 TRACE("address is 0x%08x, mask is 0x%08x\n", AddrEntries
[j
].iae_addr
, AddrEntries
[j
].iae_mask
);
678 //FIXME: For now reactos only supports unicast addresses
679 if (!(Flags
& GAA_FLAG_SKIP_UNICAST
))
681 ULONG Size
= sizeof(IP_ADAPTER_UNICAST_ADDRESS
) + sizeof(SOCKADDR
);
683 if (Ptr
&& (RemainingSize
>= Size
))
685 PIP_ADAPTER_UNICAST_ADDRESS UnicastAddress
= (PIP_ADAPTER_UNICAST_ADDRESS
)Ptr
;
687 /* Fill in the structure */
688 UnicastAddress
->Length
= sizeof(IP_ADAPTER_UNICAST_ADDRESS
);
689 UnicastAddress
->Next
= CurrentAA
->FirstUnicastAddress
;
691 // FIXME: Put meaningful value here
692 UnicastAddress
->Flags
= 0;
693 UnicastAddress
->PrefixOrigin
= IpPrefixOriginOther
;
694 UnicastAddress
->SuffixOrigin
= IpSuffixOriginOther
;
695 UnicastAddress
->DadState
= IpDadStatePreferred
;
696 UnicastAddress
->ValidLifetime
= 0xFFFFFFFF;
697 UnicastAddress
->PreferredLifetime
= 0xFFFFFFFF;
699 /* Set the address */
700 //FIXME: ipv4 only (again...)
701 UnicastAddress
->Address
.lpSockaddr
= (LPSOCKADDR
)(UnicastAddress
+ 1);
702 UnicastAddress
->Address
.iSockaddrLength
= sizeof(SOCKADDR
);
703 UnicastAddress
->Address
.lpSockaddr
->sa_family
= AF_INET
;
704 ((LPSOCKADDR_IN
)UnicastAddress
->Address
.lpSockaddr
)->sin_port
= 0;
705 memcpy(&((LPSOCKADDR_IN
)UnicastAddress
->Address
.lpSockaddr
)->sin_addr
, &AddrEntries
[j
].iae_addr
, sizeof(AddrEntries
[j
].iae_addr
));
707 CurrentAA
->FirstUnicastAddress
= UnicastAddress
;
709 RemainingSize
-= Size
;
715 if (Flags
& GAA_FLAG_INCLUDE_PREFIX
)
717 ULONG Size
= sizeof(IP_ADAPTER_PREFIX
) + sizeof(SOCKADDR
);
719 if (Ptr
&& (RemainingSize
>= Size
))
721 PIP_ADAPTER_PREFIX Prefix
= (PIP_ADAPTER_PREFIX
)Ptr
;
723 /* Fill in the structure */
724 Prefix
->Length
= sizeof(IP_ADAPTER_PREFIX
);
725 Prefix
->Next
= CurrentAA
->FirstPrefix
;
727 /* Set the address */
728 //FIXME: ipv4 only (again...)
729 Prefix
->Address
.lpSockaddr
= (LPSOCKADDR
)(Prefix
+ 1);
730 Prefix
->Address
.iSockaddrLength
= sizeof(AddrEntries
[j
].iae_mask
);
731 Prefix
->Address
.lpSockaddr
->sa_family
= AF_INET
;
732 memcpy(Prefix
->Address
.lpSockaddr
->sa_data
, &AddrEntries
[j
].iae_mask
, sizeof(AddrEntries
[j
].iae_mask
));
734 /* Compute the prefix size */
735 _BitScanReverse(&Prefix
->PrefixLength
, AddrEntries
[j
].iae_mask
);
737 CurrentAA
->FirstPrefix
= Prefix
;
739 RemainingSize
-= Size
;
746 HeapFree(GetProcessHeap(), 0, AddrEntries
);
752 HeapFree(GetProcessHeap(), 0, InterfacesList
);
754 *pOutBufLen
= TotalSize
;
755 TRACE("TotalSize: %x\n", *pOutBufLen
);
756 return ERROR_SUCCESS
;
759 ERR("Failed! Status 0x%08x\n", Status
);
761 HeapFree(GetProcessHeap(), 0, InterfacesList
);
763 return RtlNtStatusToDosError(Status
);