Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/tests/rtl.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 62662cb438..3e1d92c3d2 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -1212,12 +1212,23 @@ static struct { "1", STATUS_SUCCESS, 1, { 0, 0, 0, 1 }, strict_diff_4, STATUS_INVALID_PARAMETER, 1, { -1 } }, { "-1", STATUS_INVALID_PARAMETER, 0, { -1 } }, + { "1.2", STATUS_SUCCESS, 3, { 1, 0, 0, 2 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 3, { -1 } }, + { "1000.2000", STATUS_INVALID_PARAMETER, 9, { -1 } }, + { "1.2.", STATUS_INVALID_PARAMETER, 4, { -1 } }, + { "1..2", STATUS_INVALID_PARAMETER, 3, { -1 } }, + { "1...2", STATUS_INVALID_PARAMETER, 3, { -1 } }, + { "1.2.3", STATUS_SUCCESS, 5, { 1, 2, 0, 3 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 5, { -1 } }, + { "1.2.3.", STATUS_INVALID_PARAMETER, 6, { -1 } }, { "203569230", STATUS_SUCCESS, 9, { 12, 34, 56, 78 }, strict_diff_4, STATUS_INVALID_PARAMETER, 9, { -1 } }, { "1.223756", STATUS_SUCCESS, 8, { 1, 3, 106, 12 }, strict_diff_4, STATUS_INVALID_PARAMETER, 8, { -1 } }, { "3.4.756", STATUS_SUCCESS, 7, { 3, 4, 2, 244 }, strict_diff_4, STATUS_INVALID_PARAMETER, 7, { -1 } }, + { "756.3.4", STATUS_INVALID_PARAMETER, 7, { -1 } }, + { "3.756.4", STATUS_INVALID_PARAMETER, 7, { -1 } }, { "3.4.756.1", STATUS_INVALID_PARAMETER, 9, { -1 } }, { "3.4.65536", STATUS_INVALID_PARAMETER, 9, { -1 } }, { "3.4.5.6.7", STATUS_INVALID_PARAMETER, 7, { -1 } }, @@ -1233,9 +1244,27 @@ static struct { ".1", STATUS_INVALID_PARAMETER, 1, { -1 } }, { ".1.", STATUS_INVALID_PARAMETER, 1, { -1 } }, { ".1.2.3", STATUS_INVALID_PARAMETER, 1, { -1 } }, + { ".1.2.3.4", STATUS_INVALID_PARAMETER, 1, { -1 } }, { "0.1.2.3", STATUS_SUCCESS, 7, { 0, 1, 2, 3 } }, { "0.1.2.3.", STATUS_INVALID_PARAMETER, 7, { -1 } }, { "[0.1.2.3]", STATUS_INVALID_PARAMETER, 0, { -1 } }, + { "0x00010203", STATUS_SUCCESS, 10, { 0, 1, 2, 3 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 2, { -1 } }, + { "0X00010203", STATUS_SUCCESS, 10, { 0, 1, 2, 3 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 2, { -1 } }, + { "0x1234", STATUS_SUCCESS, 6, { 0, 0, 18, 52 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 2, { -1 } }, + { "0x123456789", STATUS_SUCCESS, 11, { 35, 69, 103, 137 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 2, { -1 } }, + { "0x00010Q03", STATUS_SUCCESS, 7, { 0, 0, 0, 16 }, strict_diff_4 | ex_fail_4, + STATUS_INVALID_PARAMETER, 2, { -1 } }, + { "x00010203", STATUS_INVALID_PARAMETER, 0, { -1 } }, + { "1234BEEF", STATUS_SUCCESS, 4, { 0, 0, 4, 210 }, strict_diff_4 | ex_fail_4, + STATUS_INVALID_PARAMETER, 4, { -1 } }, + { "017700000001", STATUS_SUCCESS, 12, { 127, 0, 0, 1 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 1, { -1 } }, + { "0777", STATUS_SUCCESS, 4, { 0, 0, 1, 255 }, strict_diff_4, + STATUS_INVALID_PARAMETER, 1, { -1 } }, { "::1", STATUS_INVALID_PARAMETER, 0, { -1 } }, { ":1", STATUS_INVALID_PARAMETER, 0, { -1 } }, };
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 299bface9a..93beba07c1 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
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46149 Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/rtl.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index 30fcb00e05..3eb8181e32 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -1044,8 +1044,17 @@ NTSTATUS WINAPI RtlIpv4StringToAddressA(const char *str, BOOLEAN strict, const c */ 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; + char cstr[32]; + ULONG clen; + + TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, address, port); + + if (!str || !address || !port) + return STATUS_INVALID_PARAMETER; + + RtlUnicodeToMultiByteN(cstr, sizeof(cstr) - 1, &clen, str, strlenW(str)); + cstr[clen] = 0; + return ipv4_string_to_address(cstr, strict, NULL, address, port); }
/*********************************************************************** @@ -1053,8 +1062,18 @@ 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; + char cstr[32]; + ULONG clen; + const char *cterminator; + NTSTATUS ret; + + TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, terminator, address); + + RtlUnicodeToMultiByteN(cstr, sizeof(cstr) - 1, &clen, str, strlenW(str)); + cstr[clen] = 0; + ret = ipv4_string_to_address(cstr, strict, &cterminator, address, NULL); + if (terminator) *terminator = str + (cterminator - cstr); + return ret; }
/***********************************************************************
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=54483
Your paranoid android.
=== w1064v1809 (32 bit report) ===
ntdll: 16e4:rtl: unhandled exception c0000005 at 77869D4B