mirror of
https://github.com/reactos/reactos.git
synced 2024-10-06 01:13:38 +00:00
[RTL]
- Implement RtlIpv6AddressToString*. Patch by Mark Jansen. CORE-6490 svn path=/trunk/; revision=67122
This commit is contained in:
parent
d0980fb653
commit
9bbf279642
|
@ -19,6 +19,12 @@
|
|||
/* maximum length of an ipv4 port expressed as a string */
|
||||
#define IPV4_PORT_STRING_MAX_LEN 7 /* with the leading ':' */
|
||||
|
||||
/* maximum length of an ipv6 string for RtlIpv6AddressToString */
|
||||
#define RTLIPV6A2S_MAX_LEN 46
|
||||
|
||||
/* maximum length of an ipv6 string with scope and port for RtlIpv6AddressToStringEx */
|
||||
#define RTLIPV6A2SEX_MAX_LEN 65
|
||||
|
||||
/* network to host order conversion for little endian machines */
|
||||
#define WN2H(w) (((w & 0xFF00) >> 8) | ((w & 0x00FF) << 8))
|
||||
|
||||
|
@ -443,20 +449,38 @@ RtlIpv4StringToAddressExW(
|
|||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
PSTR
|
||||
NTAPI
|
||||
RtlIpv6AddressToStringA(
|
||||
_In_ const struct in6_addr *Addr,
|
||||
_Out_writes_(46) PSTR S)
|
||||
_Out_writes_(RTLIPV6A2S_MAX_LEN) PSTR S)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return NULL;
|
||||
WCHAR Buffer[RTLIPV6A2S_MAX_LEN];
|
||||
PWSTR Result;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (!S)
|
||||
return (PSTR)~0;
|
||||
|
||||
Buffer[0] = 0;
|
||||
Result = RtlIpv6AddressToStringW(Addr, Buffer);
|
||||
if (Result == (PWSTR)~0)
|
||||
return (PSTR)~0;
|
||||
|
||||
ASSERT(Result >= Buffer);
|
||||
ASSERT(Result < Buffer + RTL_NUMBER_OF(Buffer));
|
||||
|
||||
Status = RtlUnicodeToMultiByteN(S, RTLIPV6A2S_MAX_LEN, NULL, Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
|
||||
if (!NT_SUCCESS(Status))
|
||||
return (PSTR)~0;
|
||||
|
||||
return S + strlen(S);
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
|
@ -467,25 +491,135 @@ RtlIpv6AddressToStringExA(
|
|||
_Out_writes_to_(*AddressStringLength, *AddressStringLength) PSTR AddressString,
|
||||
_Inout_ PULONG AddressStringLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
WCHAR Buffer[RTLIPV6A2SEX_MAX_LEN];
|
||||
NTSTATUS Status;
|
||||
|
||||
if (!Address || !AddressString || !AddressStringLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Status = RtlIpv6AddressToStringExW(Address, ScopeId, Port, Buffer, AddressStringLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
Status = RtlUnicodeToMultiByteN(AddressString, RTLIPV6A2SEX_MAX_LEN, NULL, Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
|
||||
if (!NT_SUCCESS(Status))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
PWSTR
|
||||
NTAPI
|
||||
RtlIpv6AddressToStringW(
|
||||
_In_ const struct in6_addr *Addr,
|
||||
_Out_writes_(46) PWSTR S)
|
||||
_Out_writes_(RTLIPV6A2S_MAX_LEN) PWSTR S)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return NULL;
|
||||
NTSTATUS Status;
|
||||
UINT Parts = 8, n;
|
||||
BOOLEAN SkipOnce = TRUE;
|
||||
PWSTR End;
|
||||
size_t Remaining;
|
||||
|
||||
if (!S)
|
||||
return (PWSTR)~0;
|
||||
|
||||
Remaining = RTLIPV6A2S_MAX_LEN;
|
||||
/* does it look like an ipv4 address contained in an ipv6? http://tools.ietf.org/html/rfc2765 */
|
||||
if (!Addr->s6_words[0] && !Addr->s6_words[1] && !Addr->s6_words[2] && !Addr->s6_words[3] && Addr->s6_words[6])
|
||||
{
|
||||
PWSTR Prefix = NULL;
|
||||
if (Addr->s6_words[4] == 0xffff && !Addr->s6_words[5])
|
||||
Prefix = L"ffff:0:";
|
||||
else if (!Addr->s6_words[4] && Addr->s6_words[5] == 0xffff)
|
||||
Prefix = L"ffff:";
|
||||
else if (!Addr->s6_words[4] && !Addr->s6_words[5])
|
||||
Prefix = L"";
|
||||
if (Prefix != NULL)
|
||||
{
|
||||
Status = RtlStringCchPrintfExW(S,
|
||||
Remaining,
|
||||
&End,
|
||||
NULL,
|
||||
0,
|
||||
L"::%ls%u.%u.%u.%u",
|
||||
Prefix,
|
||||
Addr->s6_bytes[12],
|
||||
Addr->s6_bytes[13],
|
||||
Addr->s6_bytes[14],
|
||||
Addr->s6_bytes[15]);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return (PWSTR)~0;
|
||||
return End;
|
||||
}
|
||||
}
|
||||
|
||||
/* does it look like an ISATAP address? http://tools.ietf.org/html/rfc5214 */
|
||||
if (!(Addr->s6_words[4] & 0xfffd) && Addr->s6_words[5] == 0xfe5e)
|
||||
Parts = 6;
|
||||
|
||||
for (n = 0; n < Parts; ++n)
|
||||
{
|
||||
if (SkipOnce && ((n + 1) < Parts) && !Addr->s6_words[n] && !Addr->s6_words[n + 1])
|
||||
{
|
||||
SkipOnce = FALSE;
|
||||
while (!Addr->s6_words[n + 1] && (n + 1) < Parts)
|
||||
++n;
|
||||
*S++ = ':';
|
||||
Remaining--;
|
||||
if ((n + 1) >= Parts)
|
||||
{
|
||||
*S++ = ':';
|
||||
Remaining--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n)
|
||||
{
|
||||
*S++ = ':';
|
||||
Remaining--;
|
||||
}
|
||||
Status = RtlStringCchPrintfExW(S,
|
||||
Remaining,
|
||||
&End,
|
||||
&Remaining,
|
||||
0,
|
||||
L"%x",
|
||||
WN2H(Addr->s6_words[n]));
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return (PWSTR)~0;
|
||||
S = End;
|
||||
}
|
||||
}
|
||||
if (Parts < 8)
|
||||
{
|
||||
Status = RtlStringCchPrintfExW(S,
|
||||
Remaining,
|
||||
&End,
|
||||
NULL,
|
||||
0,
|
||||
L":%u.%u.%u.%u",
|
||||
Addr->s6_bytes[12],
|
||||
Addr->s6_bytes[13],
|
||||
Addr->s6_bytes[14],
|
||||
Addr->s6_bytes[15]);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return (PWSTR)~0;
|
||||
|
||||
return End;
|
||||
}
|
||||
*S = UNICODE_NULL;
|
||||
return S;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
|
@ -496,8 +630,68 @@ RtlIpv6AddressToStringExW(
|
|||
_Out_writes_to_(*AddressStringLength, *AddressStringLength) PWCHAR AddressString,
|
||||
_Inout_ PULONG AddressStringLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
WCHAR Buffer[RTLIPV6A2SEX_MAX_LEN];
|
||||
PWCHAR S = Buffer;
|
||||
NTSTATUS Status;
|
||||
ULONG Length;
|
||||
size_t Remaining;
|
||||
|
||||
if (!Address || !AddressString || !AddressStringLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (Port)
|
||||
*S++ = L'[';
|
||||
|
||||
S = RtlIpv6AddressToStringW(Address, S);
|
||||
ASSERT(S != (PCWSTR)~0);
|
||||
if (S == (PCWSTR)~0)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
ASSERT(S >= Buffer);
|
||||
ASSERT(S <= Buffer + RTLIPV6A2S_MAX_LEN + 1);
|
||||
Remaining = RTL_NUMBER_OF(Buffer) - (S - Buffer);
|
||||
ASSERT(Remaining >= RTLIPV6A2SEX_MAX_LEN - RTLIPV6A2S_MAX_LEN);
|
||||
|
||||
if (ScopeId)
|
||||
{
|
||||
Status = RtlStringCchPrintfExW(S,
|
||||
Remaining,
|
||||
&S,
|
||||
&Remaining,
|
||||
0,
|
||||
L"%%%u",
|
||||
ScopeId);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Port)
|
||||
{
|
||||
Status = RtlStringCchPrintfExW(S,
|
||||
Remaining,
|
||||
&S,
|
||||
&Remaining,
|
||||
0,
|
||||
L"]:%u",
|
||||
WN2H(Port));
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Length = S - Buffer;
|
||||
ASSERT(Buffer[Length] == UNICODE_NULL);
|
||||
if (*AddressStringLength > Length)
|
||||
{
|
||||
Status = RtlStringCchCopyW(AddressString, *AddressStringLength, Buffer);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
*AddressStringLength = Length + 1;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
*AddressStringLength = Length + 1;
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue