[PATCH 6/7] ntdll: Implement RtlIpv6AddressToString(Ex)[AW]
Alex Henrie
alexhenrie24 at gmail.com
Mon May 25 23:36:23 CDT 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46788
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
dlls/ntdll/ntdll.spec | 8 +--
dlls/ntdll/rtl.c | 129 +++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/tests/rtl.c | 14 +----
include/ip2string.h | 7 +++
4 files changed, 143 insertions(+), 15 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 7ae8a6071d..6bd0a599a9 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -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)
diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c
index 003e4a1b3b..bf91423eba 100644
--- a/dlls/ntdll/rtl.c
+++ b/dlls/ntdll/rtl.c
@@ -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)
*/
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index f83031b490..94c6b582f3 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -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);
diff --git a/include/ip2string.h b/include/ip2string.h
index 4c5f36c15f..84835d4593 100644
--- a/include/ip2string.h
+++ b/include/ip2string.h
@@ -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)
--
2.26.2
More information about the wine-devel
mailing list