[PATCH v3 1/2] ntdll: Implement RtlIpv4StringToAddress(Ex)W

Alex Henrie alexhenrie24 at gmail.com
Sun Aug 25 19:36:49 CDT 2019


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46149
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
v3: Use htons instead of open-coding it
---
 dlls/ntdll/rtl.c | 145 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 141 insertions(+), 4 deletions(-)

diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c
index e0d855138f..72ecfd937a 100644
--- a/dlls/ntdll/rtl.c
+++ b/dlls/ntdll/rtl.c
@@ -884,13 +884,150 @@ void WINAPI RtlCopyLuidAndAttributesArray(
     for (i = 0; i < Count; i++) Dest[i] = Src[i];
 }
 
+static BOOL parse_ipv4_component(const WCHAR **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;
+    WCHAR c;
+    ULONG cur_value, prev_value = 0;
+    BOOL success = FALSE;
+
+    if (**str == '.')
+    {
+        *str += 1;
+        return FALSE;
+    }
+
+    if ((*str)[0] == '0')
+    {
+        if ((*str)[1] == 'x' || (*str)[1] == 'X')
+        {
+            *str += 2;
+            if (strict) return FALSE;
+            base = 16;
+        }
+        else if ((*str)[1] >= '0' && (*str)[1] <= '9')
+        {
+            *str += 1;
+            if (strict) return FALSE;
+            base = 8;
+        }
+    }
+
+    for (cur_value = 0; **str; *str += 1)
+    {
+        c = **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 WCHAR *str, BOOL strict,
+                                       const WCHAR **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 = htons(fields[0]);
+            if (terminator) *terminator = str;
+        }
+    }
+
+    if (!terminator && *str)
+        return STATUS_INVALID_PARAMETER;
+    return STATUS_SUCCESS;
+
+error:
+    if (terminator) *terminator = str;
+    return STATUS_INVALID_PARAMETER;
+}
+
 /***********************************************************************
  * RtlIpv4StringToAddressExW [NTDLL.@]
  */
 NTSTATUS WINAPI RtlIpv4StringToAddressExW(const WCHAR *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
 {
-    FIXME("(%s, %u, %p, %p): stub\n", debugstr_w(str), strict, address, port);
-    return STATUS_NOT_IMPLEMENTED;
+    TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, address, port);
+    if (!str || !address || !port) return STATUS_INVALID_PARAMETER;
+    return ipv4_string_to_address(str, strict, NULL, address, port);
 }
 
 /***********************************************************************
@@ -898,8 +1035,8 @@ NTSTATUS WINAPI RtlIpv4StringToAddressExW(const WCHAR *str, BOOLEAN strict, IN_A
  */
 NTSTATUS WINAPI RtlIpv4StringToAddressW(const WCHAR *str, BOOLEAN strict, const WCHAR **terminator, IN_ADDR *address)
 {
-    FIXME("(%s, %u, %p, %p): stub\n", debugstr_w(str), strict, terminator, address);
-    return STATUS_NOT_IMPLEMENTED;
+    TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, terminator, address);
+    return ipv4_string_to_address(str, strict, terminator, address, NULL);
 }
 
 /***********************************************************************
-- 
2.23.0




More information about the wine-devel mailing list