wine-staging/patches/ntdll-RtlIpv4StringToAddress/0002-ntdll-Implement-RtlIpv4StringToAddress-Ex-A.patch
2019-07-10 09:49:35 +10:00

213 lines
7.4 KiB
Diff

From 602c4ef16d69695bcce9484e34fb72fb36ea8684 Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Thu, 4 Jul 2019 10:22:40 -0600
Subject: [PATCH 2/3] ntdll: Implement RtlIpv4StringToAddress(Ex)A
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46149
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>
---
dlls/ntdll/ntdll.spec | 4 +-
dlls/ntdll/rtl.c | 155 ++++++++++++++++++++++++++++
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 4 +-
3 files changed, 159 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 323d5eae77..0821da0fd5 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -757,8 +757,8 @@
@ stdcall RtlIpv4AddressToStringExA(ptr long ptr ptr)
@ stdcall RtlIpv4AddressToStringExW(ptr long ptr ptr)
@ stdcall RtlIpv4AddressToStringW(ptr ptr)
-# @ stub RtlIpv4StringToAddressA
-# @ stub RtlIpv4StringToAddressExA
+@ stdcall RtlIpv4StringToAddressA(str long ptr ptr)
+@ stdcall RtlIpv4StringToAddressExA(str long ptr ptr)
@ stdcall RtlIpv4StringToAddressExW(wstr long ptr ptr)
@ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr)
# @ stub RtlIpv6AddressToStringA
diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c
index e0d855138f..30fcb00e05 100644
--- a/dlls/ntdll/rtl.c
+++ b/dlls/ntdll/rtl.c
@@ -884,6 +884,161 @@ void WINAPI RtlCopyLuidAndAttributesArray(
for (i = 0; i < Count; i++) Dest[i] = Src[i];
}
+static BOOL parse_ipv4_component(const char **str, BOOL strict, ULONG *value)
+{
+ static const int hex_table[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2F */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4F */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5F */
+ -1, 10, 11, 12, 13, 14, 15 /* 0x60-0x66 */
+ };
+ int base = 10, d;
+ unsigned char c;
+ ULONG cur_value, prev_value = 0;
+ BOOL success = FALSE;
+
+ if (**str == '.')
+ {
+ *str += 1;
+ return FALSE;
+ }
+
+ if ((*str)[0] == '0')
+ {
+ if (tolower((*str)[1]) == 'x')
+ {
+ *str += 2;
+ if (strict) return FALSE;
+ base = 16;
+ }
+ else if (isdigit((*str)[1]))
+ {
+ *str += 1;
+ if (strict) return FALSE;
+ base = 8;
+ }
+ }
+
+ for (cur_value = 0; **str; *str += 1)
+ {
+ c = (unsigned char)**str;
+ if (c >= ARRAY_SIZE(hex_table)) break;
+ d = hex_table[c];
+ if (d == -1 || d >= base) break;
+ cur_value = cur_value * base + d;
+ success = TRUE;
+ if (cur_value < prev_value) return FALSE; /* overflow */
+ prev_value = cur_value;
+ }
+
+ if (success) *value = cur_value;
+ return success;
+}
+
+static NTSTATUS ipv4_string_to_address(const char *str, BOOL strict,
+ const char **terminator, IN_ADDR *address, USHORT *port)
+{
+ ULONG fields[4];
+ int n = 0;
+
+ for (;;)
+ {
+ if (!parse_ipv4_component(&str, strict, &fields[n]))
+ goto error;
+ n++;
+ if (*str != '.')
+ break;
+ if (n == 4)
+ goto error;
+ str++;
+ }
+
+ if (strict && n < 4)
+ goto error;
+
+ switch (n)
+ {
+ case 4:
+ if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFF || fields[3] > 0xFF)
+ goto error;
+ address->S_un.S_un_b.s_b1 = fields[0];
+ address->S_un.S_un_b.s_b2 = fields[1];
+ address->S_un.S_un_b.s_b3 = fields[2];
+ address->S_un.S_un_b.s_b4 = fields[3];
+ break;
+ case 3:
+ if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFFFF)
+ goto error;
+ address->S_un.S_un_b.s_b1 = fields[0];
+ address->S_un.S_un_b.s_b2 = fields[1];
+ address->S_un.S_un_b.s_b3 = (fields[2] & 0xFF00) >> 8;
+ address->S_un.S_un_b.s_b4 = (fields[2] & 0x00FF);
+ break;
+ case 2:
+ if (fields[0] > 0xFF || fields[1] > 0xFFFFFF)
+ goto error;
+ address->S_un.S_un_b.s_b1 = fields[0];
+ address->S_un.S_un_b.s_b2 = (fields[1] & 0xFF0000) >> 16;
+ address->S_un.S_un_b.s_b3 = (fields[1] & 0x00FF00) >> 8;
+ address->S_un.S_un_b.s_b4 = (fields[1] & 0x0000FF);
+ break;
+ case 1:
+ address->S_un.S_un_b.s_b1 = (fields[0] & 0xFF000000) >> 24;
+ address->S_un.S_un_b.s_b2 = (fields[0] & 0x00FF0000) >> 16;
+ address->S_un.S_un_b.s_b3 = (fields[0] & 0x0000FF00) >> 8;
+ address->S_un.S_un_b.s_b4 = (fields[0] & 0x000000FF);
+ break;
+ default:
+ goto error;
+ }
+
+ if (terminator) *terminator = str;
+
+ if (*str == ':')
+ {
+ str++;
+ if (!parse_ipv4_component(&str, FALSE, &fields[0]))
+ goto error;
+ if (!fields[0] || fields[0] > 0xFFFF || *str)
+ goto error;
+ if (port)
+ {
+ *port = (fields[0] << 8) | (fields[0] >> 8);
+ if (terminator) *terminator = str;
+ }
+ }
+
+ if (!terminator && *str)
+ return STATUS_INVALID_PARAMETER;
+ return STATUS_SUCCESS;
+
+error:
+ if (terminator) *terminator = str;
+ return STATUS_INVALID_PARAMETER;
+}
+
+/***********************************************************************
+ * RtlIpv4StringToAddressExA [NTDLL.@]
+ */
+NTSTATUS WINAPI RtlIpv4StringToAddressExA(const char *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
+{
+ TRACE("(%s, %u, %p, %p)\n", debugstr_a(str), strict, address, port);
+ if (!str || !address || !port) return STATUS_INVALID_PARAMETER;
+ return ipv4_string_to_address(str, strict, NULL, address, port);
+}
+
+/***********************************************************************
+ * RtlIpv4StringToAddressA [NTDLL.@]
+ */
+NTSTATUS WINAPI RtlIpv4StringToAddressA(const char *str, BOOLEAN strict, const char **terminator, IN_ADDR *address)
+{
+ TRACE("(%s, %u, %p, %p)\n", debugstr_a(str), strict, terminator, address);
+ return ipv4_string_to_address(str, strict, terminator, address, NULL);
+}
+
/***********************************************************************
* RtlIpv4StringToAddressExW [NTDLL.@]
*/
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 359e2d9e69..439cae3097 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1101,8 +1101,8 @@
@ stdcall RtlIpv4AddressToStringExA(ptr long ptr ptr)
@ stdcall RtlIpv4AddressToStringExW(ptr long ptr ptr)
@ stdcall RtlIpv4AddressToStringW(ptr ptr)
-@ stub RtlIpv4StringToAddressA
-@ stub RtlIpv4StringToAddressExA
+@ stdcall RtlIpv4StringToAddressA(str long ptr ptr) ntdll.RtlIpv4StringToAddressA
+@ stdcall RtlIpv4StringToAddressExA(str long ptr ptr) ntdll.RtlIpv4StringToAddressExA
@ stdcall RtlIpv4StringToAddressExW(wstr long ptr ptr)
@ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr)
@ stub RtlIpv6AddressToStringA
--
2.20.1