ntdll: Implement RtlIpv4StringToAddress(Ex)W.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46149 Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c9f222e775
commit
e9ee0df5d2
145
dlls/ntdll/rtl.c
145
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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue