diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index 605072aacdf..d4c68ef18b6 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -19,8 +19,10 @@ #include "config.h" +#include #include #include +#include #include #include #include @@ -3541,12 +3543,61 @@ istream* __thiscall istream_read_str(istream *this, char *str) return this; } +static LONG istream_internal_read_integer(istream *this, LONG min_value, LONG max_value, BOOL set_flag) +{ + ios *base = istream_get_ios(this); + char buffer[16]; + int num_base; + LONG ret; + + TRACE("(%p %d %d %d)\n", this, min_value, max_value, set_flag); + + num_base = istream_getint(this, buffer); + errno = 0; + ret = strtol(buffer, NULL, num_base); + /* check for overflow and whether the value fits in the output var */ + if (set_flag && errno == ERANGE) { + base->state |= IOSTATE_failbit; + } else if (ret > max_value) { + base->state |= IOSTATE_failbit; + ret = max_value; + } else if (ret < min_value) { + base->state |= IOSTATE_failbit; + ret = min_value; + } + return ret; +} + +static ULONG istream_internal_read_unsigned_integer(istream *this, LONG min_value, ULONG max_value) +{ + ios *base = istream_get_ios(this); + char buffer[16]; + int num_base; + ULONG ret; + + TRACE("(%p %d %u)\n", this, min_value, max_value); + + num_base = istream_getint(this, buffer); + errno = 0; + ret = strtoul(buffer, NULL, num_base); + /* check for overflow and whether the value fits in the output var */ + if ((ret == ULONG_MAX && errno == ERANGE) || + (ret > max_value && ret < (ULONG) min_value)) { + base->state |= IOSTATE_failbit; + ret = max_value; + } + return ret; +} + /* ??5istream@@QAEAAV0@AAF@Z */ /* ??5istream@@QEAAAEAV0@AEAF@Z */ DEFINE_THISCALL_WRAPPER(istream_read_short, 8) istream* __thiscall istream_read_short(istream *this, short *p) { - FIXME("(%p %p) stub\n", this, p); + if (istream_ipfx(this, 0)) { + *p = istream_internal_read_integer(this, SHRT_MIN, SHRT_MAX, FALSE); + istream_isfx(this); + } return this; } @@ -3555,7 +3606,10 @@ istream* __thiscall istream_read_short(istream *this, short *p) DEFINE_THISCALL_WRAPPER(istream_read_unsigned_short, 8) istream* __thiscall istream_read_unsigned_short(istream *this, unsigned short *p) { - FIXME("(%p %p) stub\n", this, p); + if (istream_ipfx(this, 0)) { + *p = istream_internal_read_unsigned_integer(this, SHRT_MIN, USHRT_MAX); + istream_isfx(this); + } return this; } @@ -3564,7 +3618,10 @@ istream* __thiscall istream_read_unsigned_short(istream *this, unsigned short *p DEFINE_THISCALL_WRAPPER(istream_read_int, 8) istream* __thiscall istream_read_int(istream *this, int *p) { - FIXME("(%p %p) stub\n", this, p); + if (istream_ipfx(this, 0)) { + *p = istream_internal_read_integer(this, INT_MIN, INT_MAX, FALSE); + istream_isfx(this); + } return this; } @@ -3573,7 +3630,10 @@ istream* __thiscall istream_read_int(istream *this, int *p) DEFINE_THISCALL_WRAPPER(istream_read_unsigned_int, 8) istream* __thiscall istream_read_unsigned_int(istream *this, unsigned int *p) { - FIXME("(%p %p) stub\n", this, p); + if (istream_ipfx(this, 0)) { + *p = istream_internal_read_unsigned_integer(this, INT_MIN, UINT_MAX); + istream_isfx(this); + } return this; } @@ -3582,7 +3642,10 @@ istream* __thiscall istream_read_unsigned_int(istream *this, unsigned int *p) DEFINE_THISCALL_WRAPPER(istream_read_long, 8) istream* __thiscall istream_read_long(istream *this, LONG *p) { - FIXME("(%p %p) stub\n", this, p); + if (istream_ipfx(this, 0)) { + *p = istream_internal_read_integer(this, LONG_MIN, LONG_MAX, TRUE); + istream_isfx(this); + } return this; } @@ -3591,7 +3654,10 @@ istream* __thiscall istream_read_long(istream *this, LONG *p) DEFINE_THISCALL_WRAPPER(istream_read_unsigned_long, 8) istream* __thiscall istream_read_unsigned_long(istream *this, ULONG *p) { - FIXME("(%p %p) stub\n", this, p); + if (istream_ipfx(this, 0)) { + *p = istream_internal_read_unsigned_integer(this, LONG_MIN, ULONG_MAX); + istream_isfx(this); + } return this; } diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index 6d97566aee8..e0e5f9152b8 100644 --- a/dlls/msvcirt/tests/msvcirt.c +++ b/dlls/msvcirt/tests/msvcirt.c @@ -329,6 +329,12 @@ static int (*__thiscall p_istream_getint)(istream*, char*); static int (*__thiscall p_istream_getdouble)(istream*, char*, int); static istream* (*__thiscall p_istream_read_char)(istream*, char*); static istream* (*__thiscall p_istream_read_str)(istream*, char*); +static istream* (*__thiscall p_istream_read_short)(istream*, short*); +static istream* (*__thiscall p_istream_read_unsigned_short)(istream*, unsigned short*); +static istream* (*__thiscall p_istream_read_int)(istream*, int*); +static istream* (*__thiscall p_istream_read_unsigned_int)(istream*, unsigned int*); +static istream* (*__thiscall p_istream_read_long)(istream*, LONG*); +static istream* (*__thiscall p_istream_read_unsigned_long)(istream*, ULONG*); /* Emulate a __thiscall */ #ifdef __i386__ @@ -546,6 +552,12 @@ static BOOL init(void) SET(p_istream_getdouble, "?getdouble@istream@@AEAAHPEADH@Z"); SET(p_istream_read_char, "??5istream@@QEAAAEAV0@AEAD@Z"); SET(p_istream_read_str, "??5istream@@QEAAAEAV0@PEAD@Z"); + SET(p_istream_read_short, "??5istream@@QEAAAEAV0@AEAF@Z"); + SET(p_istream_read_unsigned_short, "??5istream@@QEAAAEAV0@AEAG@Z"); + SET(p_istream_read_int, "??5istream@@QEAAAEAV0@AEAH@Z"); + SET(p_istream_read_unsigned_int, "??5istream@@QEAAAEAV0@AEAI@Z"); + SET(p_istream_read_long, "??5istream@@QEAAAEAV0@AEAJ@Z"); + SET(p_istream_read_unsigned_long, "??5istream@@QEAAAEAV0@AEAK@Z"); } else { p_operator_new = (void*)GetProcAddress(msvcrt, "??2@YAPAXI@Z"); p_operator_delete = (void*)GetProcAddress(msvcrt, "??3@YAXPAX@Z"); @@ -685,6 +697,12 @@ static BOOL init(void) SET(p_istream_getdouble, "?getdouble@istream@@AAEHPADH@Z"); SET(p_istream_read_char, "??5istream@@QAEAAV0@AAD@Z"); SET(p_istream_read_str, "??5istream@@QAEAAV0@PAD@Z"); + SET(p_istream_read_short, "??5istream@@QAEAAV0@AAF@Z"); + SET(p_istream_read_unsigned_short, "??5istream@@QAEAAV0@AAG@Z"); + SET(p_istream_read_int, "??5istream@@QAEAAV0@AAH@Z"); + SET(p_istream_read_unsigned_int, "??5istream@@QAEAAV0@AAI@Z"); + SET(p_istream_read_long, "??5istream@@QAEAAV0@AAJ@Z"); + SET(p_istream_read_unsigned_long, "??5istream@@QAEAAV0@AAK@Z"); } SET(p_ios_static_lock, "?x_lockc@ios@@0U_CRT_CRITICAL_SECTION@@A"); SET(p_ios_lockc, "?lockc@ios@@KAXXZ"); @@ -4868,8 +4886,15 @@ static void test_istream_read(void) char c, st[8], char_out[] = {-85, ' ', 'a', -50}; const char *str_out[] = {"AAAAAAA", "abc", "a", "abc", "ab", "abcde"}; + short s, short_out[] = {32767, -32768}; + unsigned short us, ushort_out[] = {65535u, 65534u, 32768u}; + int n, int_out[] = {123456789, 0, 1, -500, 0x8000, 2147483646, 2147483647, -2147483647, -2147483647-1, -1}; + unsigned un, uint_out[] = {4294967295u, 4294967294u, 2147483648u, 1u}; + LONG l, long_out[] = {2147483647l, -2147483647l-1}; + ULONG ul, ulong_out[] = {4294967295ul, 4294967294ul, 2147483648ul, 1ul}; struct istream_read_test { - enum { type_chr, type_str } type; + enum { type_chr, type_str, type_shrt, type_ushrt, type_int, type_uint, + type_long, type_ulong } type; const char *stream_content; ios_flags flags; int width; @@ -4902,6 +4927,71 @@ static void test_istream_read(void) {type_str, "abcde\n", 0, 0, /* "abcde" */ 5, IOSTATE_goodbit, 0, 5, FALSE}, {type_str, "\n", 0, 0, /* "AAAAAAA" */ 0, IOSTATE_failbit, 0, 0, FALSE}, {type_str, "abcde", 0, -1, /* "abcde" */ 5, IOSTATE_eofbit, 0, 5, FALSE}, + /* short */ + {type_shrt, "32767", 0, 6, /* 32767 */ 0, IOSTATE_eofbit, 6, 5, FALSE}, + {type_shrt, "32768", 0, 6, /* 32767 */ 0, IOSTATE_faileof, 6, 5, FALSE}, + {type_shrt, "2147483648", 0, 6, /* 32767 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_shrt, "4294967296", 0, 6, /* 32767 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_shrt, "-32768", 0, 6, /* -32768 */ 1, IOSTATE_eofbit, 6, 6, FALSE}, + {type_shrt, "-32769", 0, 6, /* -32768 */ 1, IOSTATE_faileof, 6, 6, FALSE}, + {type_shrt, "-2147483648", 0, 6, /* -32768 */ 1, IOSTATE_faileof, 6, 11, FALSE}, + /* unsigned short */ + {type_ushrt, "65535", 0, 6, /* 65535 */ 0, IOSTATE_eofbit, 6, 5, FALSE}, + {type_ushrt, "65536", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 5, FALSE}, + {type_ushrt, "12345678", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 8, FALSE}, + {type_ushrt, "2147483648", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_ushrt, "4294967296", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_ushrt, "99999999999999", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 14, FALSE}, + {type_ushrt, "-1", 0, 6, /* 65535 */ 0, IOSTATE_eofbit, 6, 2, TRUE}, + {type_ushrt, "-2", 0, 6, /* 65534 */ 1, IOSTATE_eofbit, 6, 2, FALSE}, + {type_ushrt, "-32768", 0, 6, /* 32768 */ 2, IOSTATE_eofbit, 6, 6, FALSE}, + {type_ushrt, "-32769", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 6, FALSE}, + {type_ushrt, "-2147483648", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 11, FALSE}, + /* int */ + {type_int, "", FLAGS_skipws, 6, /* 123456789 */ 0, IOSTATE_faileof, 6, 0, FALSE}, + {type_int, " 0", FLAGS_skipws, 6, /* 0 */ 1, IOSTATE_eofbit, 6, 2, FALSE}, + {type_int, " 0", 0, 6, /* 0 */ 1, IOSTATE_failbit, 6, 0, FALSE}, + {type_int, "+1 ", 0, 6, /* 1 */ 2, IOSTATE_goodbit, 6, 2, FALSE}, + {type_int, "1L", 0, 6, /* 1 */ 2, IOSTATE_goodbit, 6, 1, FALSE}, + {type_int, "-500.0", 0, 6, /* -500 */ 3, IOSTATE_goodbit, 6, 4, FALSE}, + {type_int, "0x8000", 0, 6, /* 0x8000 */ 4, IOSTATE_eofbit, 6, 6, FALSE}, + {type_int, "0xtest", 0, 6, /* 0 */ 1, IOSTATE_failbit, 6, 0, FALSE}, + {type_int, "0test", 0, 6, /* 0 */ 1, IOSTATE_goodbit, 6, 1, FALSE}, + {type_int, "0x7ffffffe", 0, 6, /* 2147483646 */ 5, IOSTATE_eofbit, 6, 10, FALSE}, + {type_int, "0x7fffffff", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE}, + {type_int, "0x80000000", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE}, + {type_int, "0xdeadbeef", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE}, + {type_int, "2147483648", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE}, + {type_int, "4294967295", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE}, + {type_int, "-2147483647", 0, 6, /* -2147483647 */ 7, IOSTATE_eofbit, 6, 11, FALSE}, + {type_int, "-2147483648", 0, 6, /* -2147483648 */ 8, IOSTATE_eofbit, 6, 11, FALSE}, + {type_int, "-2147483649", 0, 6, /* -2147483648 */ 8, IOSTATE_eofbit, 6, 11, FALSE}, + {type_int, "-1f", FLAGS_dec, 6, /* -1 */ 9, IOSTATE_goodbit, 6, 2, FALSE}, + /* unsigned int */ + {type_uint, "4294967295", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 10, TRUE}, + {type_uint, "4294967296", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_uint, "99999999999999", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 14, FALSE}, + {type_uint, "-1", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 2, TRUE}, + {type_uint, "-2", 0, 6, /* 4294967294 */ 1, IOSTATE_eofbit, 6, 2, FALSE}, + {type_uint, "-2147483648", 0, 6, /* 2147483648 */ 2, IOSTATE_eofbit, 6, 11, FALSE}, + {type_uint, "-4294967295", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 11, FALSE}, + {type_uint, "-9999999999999", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 14, FALSE}, + /* long */ + {type_long, "2147483647", 0, 6, /* 2147483647 */ 0, IOSTATE_eofbit, 6, 10, TRUE}, + {type_long, "2147483648", 0, 6, /* 2147483647 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_long, "4294967295", 0, 6, /* 2147483647 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_long, "-2147483648", 0, 6, /* -2147483648 */ 1, IOSTATE_eofbit, 6, 11, TRUE}, + {type_long, "-2147483649", 0, 6, /* -2147483648 */ 1, IOSTATE_faileof, 6, 11, FALSE}, + {type_long, "-9999999999999", 0, 6, /* -2147483648 */ 1, IOSTATE_faileof, 6, 14, FALSE}, + /* unsigned long */ + {type_ulong, "4294967295", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 10, TRUE}, + {type_ulong, "4294967296", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 10, FALSE}, + {type_ulong, "99999999999999", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 14, FALSE}, + {type_ulong, "-1", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 2, TRUE}, + {type_ulong, "-2", 0, 6, /* 4294967294 */ 1, IOSTATE_eofbit, 6, 2, FALSE}, + {type_ulong, "-2147483648", 0, 6, /* 2147483648 */ 2, IOSTATE_eofbit, 6, 11, FALSE}, + {type_ulong, "-4294967295", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 11, FALSE}, + {type_ulong, "-9999999999999", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 14, FALSE}, }; pssb = call_func2(p_strstreambuf_dynamic_ctor, &ssb, 64); @@ -4934,6 +5024,42 @@ static void test_istream_read(void) ok(!strcmp(st, str_out[tests[i].expected_val]), "Test %d: expected %s got %s\n", i, str_out[tests[i].expected_val], st); break; + case type_shrt: + s = 12345; + pis = call_func2(p_istream_read_short, &is, &s); + ok(s == short_out[tests[i].expected_val], "Test %d: expected %hd got %hd\n", i, + short_out[tests[i].expected_val], s); + break; + case type_ushrt: + us = 12345u; + pis = call_func2(p_istream_read_unsigned_short, &is, &us); + ok(us == ushort_out[tests[i].expected_val], "Test %d: expected %hu got %hu\n", i, + ushort_out[tests[i].expected_val], us); + break; + case type_int: + n = 123456789; + pis = call_func2(p_istream_read_int, &is, &n); + ok(n == int_out[tests[i].expected_val], "Test %d: expected %d got %d\n", i, + int_out[tests[i].expected_val], n); + break; + case type_uint: + un = 123456789u; + pis = call_func2(p_istream_read_unsigned_int, &is, &un); + ok(un == uint_out[tests[i].expected_val], "Test %d: expected %u got %u\n", i, + uint_out[tests[i].expected_val], un); + break; + case type_long: + l = 123456789l; + pis = call_func2(p_istream_read_long, &is, &l); + ok(l == long_out[tests[i].expected_val], "Test %d: expected %d got %d\n", i, + long_out[tests[i].expected_val], l); + break; + case type_ulong: + ul = 123456789ul; + pis = call_func2(p_istream_read_unsigned_long, &is, &ul); + ok(ul == ulong_out[tests[i].expected_val], "Test %d: expected %u got %u\n", i, + ulong_out[tests[i].expected_val], ul); + break; } ok(pis == &is, "Test %d: wrong return, expected %p got %p\n", i, &is, pis);