ntdll: Implement RtlIpv6AddressToString(Ex)[AW].

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46788
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alex Henrie 2020-05-25 22:36:23 -06:00 committed by Alexandre Julliard
parent e5f69e81f3
commit 0af08318b7
5 changed files with 147 additions and 19 deletions

View File

@ -784,10 +784,10 @@
@ stdcall RtlIpv4StringToAddressExA(str long ptr ptr)
@ stdcall RtlIpv4StringToAddressExW(wstr long ptr ptr)
@ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr)
# @ stub RtlIpv6AddressToStringA
# @ stub RtlIpv6AddressToStringExA
# @ stub RtlIpv6AddressToStringExW
# @ stub RtlIpv6AddressToStringW
@ stdcall RtlIpv6AddressToStringA(ptr ptr)
@ stdcall RtlIpv6AddressToStringExA(ptr long long ptr ptr)
@ stdcall RtlIpv6AddressToStringExW(ptr long long ptr ptr)
@ stdcall RtlIpv6AddressToStringW(ptr ptr)
@ stdcall RtlIpv6StringToAddressA(str ptr ptr)
@ stdcall RtlIpv6StringToAddressExA(str ptr ptr ptr)
@ stdcall RtlIpv6StringToAddressExW(wstr ptr ptr ptr)

View File

@ -1412,6 +1412,135 @@ CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
return buffer + size - 1;
}
static BOOL is_ipv4_in_ipv6(const IN6_ADDR *address)
{
if (address->s6_words[5] == htons(0x5efe) && (address->s6_words[4] & ~htons(0x200)) == 0)
return TRUE;
if (*(UINT64 *)address != 0)
return FALSE;
if (address->s6_words[4] != 0 && address->s6_words[4] != 0xffff)
return FALSE;
if (address->s6_words[4] == 0 && address->s6_words[5] != 0 && address->s6_words[5] != 0xffff)
return FALSE;
if (address->s6_words[4] == 0xffff && address->s6_words[5] != 0)
return FALSE;
if (address->s6_words[6] == 0)
return FALSE;
return TRUE;
}
/***********************************************************************
* RtlIpv6AddressToStringExA [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6AddressToStringExA(const IN6_ADDR *address, ULONG scope, USHORT port, char *str, ULONG *size)
{
char buffer[64], *p = buffer;
int i, len, gap = -1, gap_len = 1, ipv6_end = 8;
ULONG needed;
NTSTATUS ret;
TRACE("(%p %u %u %p %p)\n", address, scope, port, str, size);
if (!address || !str || !size)
return STATUS_INVALID_PARAMETER;
if (is_ipv4_in_ipv6(address))
ipv6_end = 6;
for (i = 0; i < ipv6_end; i++)
{
len = 0;
while (!address->s6_words[i] && i < ipv6_end)
{
i++;
len++;
}
if (len > gap_len)
{
gap = i - len;
gap_len = len;
}
}
if (port) p += sprintf(p, "[");
i = 0;
while (i < ipv6_end)
{
if (i == gap)
{
p += sprintf(p, ":");
i += gap_len;
if (i == ipv6_end) p += sprintf(p, ":");
continue;
}
if (i > 0) p += sprintf(p, ":");
p += sprintf(p, "%x", ntohs(address->s6_words[i]));
i++;
}
if (ipv6_end == 6)
{
if (p[-1] != ':') p += sprintf(p, ":");
p = RtlIpv4AddressToStringA((IN_ADDR *)(address->s6_words + 6), p);
}
if (scope) p += sprintf(p, "%%%u", scope);
if (port) p += sprintf(p, "]:%u", ntohs(port));
needed = p - buffer + 1;
if (*size >= needed)
{
strcpy(str, buffer);
ret = STATUS_SUCCESS;
}
else
{
ret = STATUS_INVALID_PARAMETER;
}
*size = needed;
return ret;
}
/***********************************************************************
* RtlIpv6AddressToStringA [NTDLL.@]
*/
char * WINAPI RtlIpv6AddressToStringA(const IN6_ADDR *address, char *str)
{
ULONG size = 46;
if (!address || !str) return str - 1;
str[45] = 0; /* this byte is set even though the string is always shorter */
RtlIpv6AddressToStringExA(address, 0, 0, str, &size);
return str + size - 1;
}
/***********************************************************************
* RtlIpv6AddressToStringExW [NTDLL.@]
*/
NTSTATUS WINAPI RtlIpv6AddressToStringExW(const IN6_ADDR *address, ULONG scope, USHORT port, WCHAR *str, ULONG *size)
{
char cstr[64];
NTSTATUS ret = RtlIpv6AddressToStringExA(address, scope, port, cstr, size);
if (ret == STATUS_SUCCESS) RtlMultiByteToUnicodeN(str, *size * sizeof(WCHAR), NULL, cstr, *size);
return ret;
}
/***********************************************************************
* RtlIpv6AddressToStringW [NTDLL.@]
*/
WCHAR * WINAPI RtlIpv6AddressToStringW(const IN6_ADDR *address, WCHAR *str)
{
ULONG size = 46;
if (!address || !str) return str;
str[45] = 0; /* this word is set even though the string is always shorter */
if (RtlIpv6AddressToStringExW(address, 0, 0, str, &size) != STATUS_SUCCESS)
return str;
return str + size - 1;
}
/***********************************************************************
* get_pointer_obfuscator (internal)
*/

View File

@ -73,7 +73,6 @@ static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD);
static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
static NTSTATUS (WINAPI *pRtlIpv4StringToAddressExA)(PCSTR, BOOLEAN, IN_ADDR *, PUSHORT);
static CHAR * (WINAPI *pRtlIpv6AddressToStringA)(struct in6_addr *, PSTR);
static NTSTATUS (WINAPI *pRtlIpv6AddressToStringExA)(struct in6_addr *, ULONG, USHORT, PCHAR, PULONG);
static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExA)(PCSTR, struct in6_addr *, PULONG, PUSHORT);
static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExW)(PCWSTR, struct in6_addr *, PULONG, PUSHORT);
@ -114,7 +113,6 @@ static void InitFunctionPtrs(void)
pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode");
pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA");
pRtlIpv4StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressExA");
pRtlIpv6AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv6AddressToStringA");
pRtlIpv6AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv6AddressToStringExA");
pRtlIpv6StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressExA");
pRtlIpv6StringToAddressExW = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressExW");
@ -1801,22 +1799,16 @@ static void test_RtlIpv6AddressToString(void)
};
unsigned int i;
if (!pRtlIpv6AddressToStringA)
{
skip("RtlIpv6AddressToStringA not available\n");
return;
}
memset(buffer, '#', sizeof(buffer));
buffer[sizeof(buffer)-1] = 0;
memset(&ip, 0, sizeof(ip));
result = pRtlIpv6AddressToStringA(&ip, buffer);
result = RtlIpv6AddressToStringA(&ip, buffer);
len = strlen(buffer);
ok(result == (buffer + len) && !strcmp(buffer, "::"),
"got %p with '%s' (expected %p with '::')\n", result, buffer, buffer + len);
result = pRtlIpv6AddressToStringA(&ip, NULL);
result = RtlIpv6AddressToStringA(&ip, NULL);
ok(result == (LPCSTR)~0 || broken(result == (LPCSTR)len) /* WinXP / Win2k3 */,
"got %p, expected %p\n", result, (LPCSTR)~0);
@ -1826,7 +1818,7 @@ static void test_RtlIpv6AddressToString(void)
memset(buffer, '#', sizeof(buffer));
buffer[sizeof(buffer)-1] = 0;
result = pRtlIpv6AddressToStringA(&ip, buffer);
result = RtlIpv6AddressToStringA(&ip, buffer);
len = strlen(buffer);
ok(result == (buffer + len) && !strcmp(buffer, tests[i].address),
"got %p with '%s' (expected %p with '%s')\n", result, buffer, buffer + len, tests[i].address);

View File

@ -1134,10 +1134,10 @@
@ stdcall RtlIpv4StringToAddressExA(str long ptr ptr)
@ stdcall RtlIpv4StringToAddressExW(wstr long ptr ptr)
@ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr)
@ stub RtlIpv6AddressToStringA
@ stub RtlIpv6AddressToStringExA
@ stub RtlIpv6AddressToStringExW
@ stub RtlIpv6AddressToStringW
@ stdcall RtlIpv6AddressToStringA(ptr ptr)
@ stdcall RtlIpv6AddressToStringExA(ptr long long ptr ptr)
@ stdcall RtlIpv6AddressToStringExW(ptr long long ptr ptr)
@ stdcall RtlIpv6AddressToStringW(ptr ptr)
@ stdcall RtlIpv6StringToAddressA(str ptr ptr)
@ stdcall RtlIpv6StringToAddressExA(str ptr ptr ptr)
@ stdcall RtlIpv6StringToAddressExW(wstr ptr ptr ptr)

View File

@ -30,6 +30,13 @@ NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *address, USHORT port, c
NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *address, USHORT port, WCHAR *str, ULONG *size);
#define RtlIpv4AddressToStringEx WINELIB_NAME_AW(RtlIpv4AddressToStringEx)
char * WINAPI RtlIpv6AddressToStringA(const IN6_ADDR *address, char *str);
WCHAR * WINAPI RtlIpv6AddressToStringW(const IN6_ADDR *address, WCHAR *str);
#define RtlIpv6AddressToString WINELIB_NAME_AW(RtlIpv6AddressToString)
NTSTATUS WINAPI RtlIpv6AddressToStringExA(const IN6_ADDR *address, LONG scope, USHORT port, char *str, ULONG *size);
NTSTATUS WINAPI RtlIpv6AddressToStringExW(const IN6_ADDR *address, LONG scope, USHORT port, WCHAR *str, ULONG *size);
#define RtlIpv6AddressToStringEx WINELIB_NAME_AW(RtlIpv6AddressToStringEx)
NTSTATUS WINAPI RtlIpv4StringToAddressA(const char *str, BOOLEAN strict, const char **terminator, IN_ADDR *address);
NTSTATUS WINAPI RtlIpv4StringToAddressW(const WCHAR *str, BOOLEAN strict, const WCHAR **terminator, IN_ADDR *address);
#define RtlIpv4StringToAddress WINELIB_NAME_AW(RtlIpv4StringToAddress)