diff --git a/patches/Makefile b/patches/Makefile index e106ef08..f82af287 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -545,7 +545,7 @@ kernel32-Named_Pipe.ok: # Patchset kernel32-UTF7_Support # | # | Included patches: -# | * Support for UTF7 encoding/decoding [rev 2, by Alex Henrie] +# | * Support for UTF7 encoding/decoding [rev 3, by Alex Henrie] # | # | This patchset fixes the following Wine bugs: # | * [#27388] Support for UTF7 encoding/decoding @@ -559,7 +559,7 @@ kernel32-UTF7_Support.ok: $(call APPLY_FILE,kernel32-UTF7_Support/0002-kernel32-Support-UTF-7-in-WideCharToMultiByte.patch) $(call APPLY_FILE,kernel32-UTF7_Support/0003-kernel32-tests-Add-tests-for-UTF-7-conversion.patch) @( \ - echo '+ { "kernel32-UTF7_Support", "Alex Henrie", "Support for UTF7 encoding/decoding [rev 2]" },'; \ + echo '+ { "kernel32-UTF7_Support", "Alex Henrie", "Support for UTF7 encoding/decoding [rev 3]" },'; \ ) > kernel32-UTF7_Support.ok # Patchset libs-Unicode_Collation diff --git a/patches/kernel32-UTF7_Support/0001-kernel32-Support-UTF-7-in-MultiByteToWideChar.patch b/patches/kernel32-UTF7_Support/0001-kernel32-Support-UTF-7-in-MultiByteToWideChar.patch index 129de4c6..b56d757d 100644 --- a/patches/kernel32-UTF7_Support/0001-kernel32-Support-UTF-7-in-MultiByteToWideChar.patch +++ b/patches/kernel32-UTF7_Support/0001-kernel32-Support-UTF-7-in-MultiByteToWideChar.patch @@ -1,32 +1,32 @@ -From 8e54f8c98655c08b09d3a5ce6a27d5e6a1c1c5e3 Mon Sep 17 00:00:00 2001 +From a8bf53baa972197e228ea01701d5992a11151824 Mon Sep 17 00:00:00 2001 From: Alex Henrie -Date: Thu, 9 Oct 2014 14:13:00 -0600 +Date: Fri, 17 Oct 2014 12:54:02 -0600 Subject: kernel32: Support UTF-7 in MultiByteToWideChar. Portions of utf7_mbstowcs were written by Sebastian Lackner --- - dlls/kernel32/locale.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 156 insertions(+), 4 deletions(-) + dlls/kernel32/locale.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 150 insertions(+), 3 deletions(-) diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c -index 730574b..6ccb799 100644 +index 730574b..0123124 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c -@@ -1954,6 +1954,159 @@ BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD fla +@@ -1954,6 +1954,154 @@ BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD fla /*********************************************************************** -+ * write_to_w_string ++ * utf7_write_w + * + * Helper for utf7_mbstowcs + * + * RETURNS + * TRUE on success, FALSE on error + */ -+static inline BOOL write_to_w_string(WCHAR *dst, int dstlen, int *index, WCHAR character) ++static inline BOOL utf7_write_w(WCHAR *dst, int dstlen, int *index, WCHAR character) +{ -+ if (dst) ++ if (dstlen > 0) + { + if (*index >= dstlen) + return FALSE; @@ -50,39 +50,39 @@ index 730574b..6ccb799 100644 + */ +static int utf7_mbstowcs(const char *src, int srclen, WCHAR *dst, int dstlen) +{ -+ static const WCHAR base64_decoding_table[] = { -+ /* \0 */ -1, /* \x01 */ -1, /* \x02 */ -1, /* \x03 */ -1, -+ /* \x04 */ -1, /* \x05 */ -1, /* \x06 */ -1, /* \a */ -1, -+ /* \b */ -1, /* \t */ -1, /* \n */ -1, /* \v */ -1, -+ /* \f */ -1, /* \r */ -1, /* \x0E */ -1, /* \x0F */ -1, -+ /* \x10 */ -1, /* \x11 */ -1, /* \x12 */ -1, /* \x13 */ -1, -+ /* \x14 */ -1, /* \x15 */ -1, /* \x16 */ -1, /* \x17 */ -1, -+ /* \x18 */ -1, /* \x19 */ -1, /* \x1A */ -1, /* \e */ -1, -+ /* \x1C */ -1, /* \x1D */ -1, /* \x1E */ -1, /* \x1F */ -1, -+ /* */ -1, /* ! */ -1, /* " */ -1, /* # */ -1, -+ /* $ */ -1, /* % */ -1, /* & */ -1, /* ' */ -1, -+ /* ( */ -1, /* ) */ -1, /* * */ -1, /* + */ 62, -+ /* , */ -1, /* - */ -1, /* . */ -1, /* / */ 63, -+ /* 0 */ 52, /* 1 */ 53, /* 2 */ 54, /* 3 */ 55, -+ /* 4 */ 56, /* 5 */ 57, /* 6 */ 58, /* 7 */ 59, -+ /* 8 */ 60, /* 9 */ 61, /* : */ -1, /* ; */ -1, -+ /* < */ -1, /* = */ -1, /* > */ -1, /* ? */ -1, -+ /* @ */ -1, /* A */ 0, /* B */ 1, /* C */ 2, -+ /* D */ 3, /* E */ 4, /* F */ 5, /* G */ 6, -+ /* H */ 7, /* I */ 8, /* J */ 9, /* K */ 10, -+ /* L */ 11, /* M */ 12, /* N */ 13, /* O */ 14, -+ /* P */ 15, /* Q */ 16, /* R */ 17, /* S */ 18, -+ /* T */ 19, /* U */ 20, /* V */ 21, /* W */ 22, -+ /* X */ 23, /* Y */ 24, /* Z */ 25, /* [ */ -1, -+ /* \ */ -1, /* ] */ -1, /* ^ */ -1, /* _ */ -1, -+ /* ` */ -1, /* a */ 26, /* b */ 27, /* c */ 28, -+ /* d */ 29, /* e */ 30, /* f */ 31, /* g */ 32, -+ /* h */ 33, /* i */ 34, /* j */ 35, /* k */ 36, -+ /* l */ 37, /* m */ 38, /* n */ 39, /* o */ 40, -+ /* p */ 41, /* q */ 42, /* r */ 43, /* s */ 44, -+ /* t */ 45, /* u */ 46, /* v */ 47, /* w */ 48, -+ /* x */ 49, /* y */ 50, /* z */ 51, /* { */ -1, -+ /* | */ -1, /* } */ -1, /* ~ */ -1, /* \x7F */ -1 ++ static const signed char base64_decoding_table[] = { ++ /* \0 \x01 \x02 \x03 \x04 \x05 \x06 \a */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* \b \t \n \v \f \r \x0E \x0F */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* \x18 \x19 \x1A \e \x1C \x1D \x1E \x1F */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* ! " # $ % & ' */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* ( ) * + , - . / */ ++ -1, -1, -1, 62, -1, -1, -1, 63, ++ /* 0 1 2 3 4 5 6 7 */ ++ 52, 53, 54, 55, 56, 57, 58, 59, ++ /* 8 9 : ; < = > ? */ ++ 60, 61, -1, -1, -1, -1, -1, -1, ++ /* @ A B C D E F G */ ++ -1, 0, 1, 2, 3, 4, 5, 6, ++ /* H I J K L M N O */ ++ 7, 8, 9, 10, 11, 12, 13, 14, ++ /* P Q R S T U V W */ ++ 15, 16, 17, 18, 19, 20, 21, 22, ++ /* X Y Z [ \ ] ^ _ */ ++ 23, 24, 25, -1, -1, -1, -1, -1, ++ /* ` a b c d e f g */ ++ -1, 26, 27, 28, 29, 30, 31, 32, ++ /* h i j k l m n o */ ++ 33, 34, 35, 36, 37, 38, 39, 40, ++ /* p q r s t u v w */ ++ 41, 42, 43, 44, 45, 46, 47, 48, ++ /* x y z { | } ~ \x7F */ ++ 49, 50, 51, -1, -1, -1, -1, -1 + }; + + const char *source_end = src + srclen; @@ -91,21 +91,18 @@ index 730574b..6ccb799 100644 + DWORD byte_pair = 0; + short offset = 0; + -+ if (!dstlen) -+ dst = NULL; -+ + while (src < source_end) + { + if (*src == '+') + { -+ src++; /* skip the + sign */ ++ src++; + if (src >= source_end) + break; + + if (*src == '-') + { + /* just a plus sign escaped as +- */ -+ if (!write_to_w_string(dst, dstlen, &dest_index, '+')) ++ if (!utf7_write_w(dst, dstlen, &dest_index, '+')) + return -1; + src++; + continue; @@ -113,7 +110,7 @@ index 730574b..6ccb799 100644 + + do + { -+ WCHAR sextet = *src; ++ signed char sextet = *src; + if (sextet == '-') + { + /* skip over the dash and end base64 decoding */ @@ -122,45 +119,43 @@ index 730574b..6ccb799 100644 + offset = 0; + break; + } -+ else if (sextet <= 127) ++ if (sextet < 0) + { -+ sextet = base64_decoding_table[sextet]; -+ if (sextet == (WCHAR)-1) -+ { -+ /* -1 means that the next character of src is not part of a base64 sequence */ -+ /* in other words, all sextets in this base64 sequence have been processed */ -+ /* the current, unfinished byte pair is discarded */ -+ offset = 0; -+ break; -+ } -+ } -+ else -+ { -+ /* the next character of src is > 127 and therefore not part of a base64 sequence */ ++ /* the next character of src is < 0 and therefore not part of a base64 sequence */ + /* the current, unfinished byte pair is NOT discarded in this case */ + /* this is probably a bug in Windows */ + break; + } + ++ sextet = base64_decoding_table[sextet]; ++ if (sextet == -1) ++ { ++ /* -1 means that the next character of src is not part of a base64 sequence */ ++ /* in other words, all sextets in this base64 sequence have been processed */ ++ /* the current, unfinished byte pair is discarded */ ++ offset = 0; ++ break; ++ } ++ + byte_pair = (byte_pair << 6) | sextet; + offset += 6; + + if (offset >= 16) + { + /* this byte pair is done */ -+ if (!write_to_w_string(dst, dstlen, &dest_index, (byte_pair >> (offset - 16)) & 0xFFFF)) ++ if (!utf7_write_w(dst, dstlen, &dest_index, (byte_pair >> (offset - 16)) & 0xFFFF)) + return -1; + offset -= 16; + } + -+ /* this sextet is done */ + src++; -+ } while (src < source_end); ++ } ++ while (src < source_end); + } + else + { -+ /* we have to convert to unsigned char in case *src > 127 */ -+ if (!write_to_w_string(dst, dstlen, &dest_index, (unsigned char)*src)) ++ /* we have to convert to unsigned char in case *src < 0 */ ++ if (!utf7_write_w(dst, dstlen, &dest_index, (unsigned char)*src)) + return -1; + src++; + } @@ -173,16 +168,7 @@ index 730574b..6ccb799 100644 * MultiByteToWideChar (KERNEL32.@) * * Convert a multibyte character string into a Unicode string. -@@ -1963,7 +2116,7 @@ BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD fla - * flags [I] Character mapping flags - * src [I] Source string buffer - * srclen [I] Length of src (in bytes), or -1 if src is NUL terminated -- * dst [O] Destination buffer -+ * dst [O] Destination buffer, or NULL to compute the required length - * dstlen [I] Length of dst (in WCHARs), or 0 to compute the required length - * - * RETURNS -@@ -2006,9 +2159,8 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, +@@ -2006,9 +2154,8 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, SetLastError( ERROR_INVALID_FLAGS ); return 0; } diff --git a/patches/kernel32-UTF7_Support/0002-kernel32-Support-UTF-7-in-WideCharToMultiByte.patch b/patches/kernel32-UTF7_Support/0002-kernel32-Support-UTF-7-in-WideCharToMultiByte.patch index 057f7873..e76bf272 100644 --- a/patches/kernel32-UTF7_Support/0002-kernel32-Support-UTF-7-in-WideCharToMultiByte.patch +++ b/patches/kernel32-UTF7_Support/0002-kernel32-Support-UTF-7-in-WideCharToMultiByte.patch @@ -1,76 +1,77 @@ -From 102cc040e57795ac5287e47194620db8419adcf4 Mon Sep 17 00:00:00 2001 +From 02cb021277295aa3a2166e2497a686d2ebb32126 Mon Sep 17 00:00:00 2001 From: Alex Henrie -Date: Thu, 9 Oct 2014 14:07:39 -0600 +Date: Fri, 17 Oct 2014 15:40:51 -0600 Subject: kernel32: Support UTF-7 in WideCharToMultiByte. Portions of utf7_wcstombs were written by Sebastian Lackner --- - dlls/kernel32/locale.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 143 insertions(+), 4 deletions(-) + dlls/kernel32/locale.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 145 insertions(+), 3 deletions(-) diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c -index 6ccb799..b412851 100644 +index 0123124..6c2b6e7 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c -@@ -2200,6 +2200,146 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, +@@ -2195,6 +2195,149 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, /*********************************************************************** -+ * can_directly_encode ++ * utf7_can_directly_encode + * + * Helper for utf7_wcstombs + */ +static inline BOOL utf7_can_directly_encode(WCHAR codepoint) +{ + static const BOOL directly_encodable_table[] = { -+ /* \0 */ TRUE, /* \x01 */ FALSE, /* \x02 */ FALSE, /* \x03 */ FALSE, -+ /* \x04 */ FALSE, /* \x05 */ FALSE, /* \x06 */ FALSE, /* \a */ FALSE, -+ /* \b */ FALSE, /* \t */ TRUE, /* \n */ TRUE, /* \v */ FALSE, -+ /* \f */ FALSE, /* \r */ TRUE, /* \x0E */ FALSE, /* \x0F */ FALSE, -+ /* \x10 */ FALSE, /* \x11 */ FALSE, /* \x12 */ FALSE, /* \x13 */ FALSE, -+ /* \x14 */ FALSE, /* \x15 */ FALSE, /* \x16 */ FALSE, /* \x17 */ FALSE, -+ /* \x18 */ FALSE, /* \x19 */ FALSE, /* \x1A */ FALSE, /* \e */ FALSE, -+ /* \x1C */ FALSE, /* \x1D */ FALSE, /* \x1E */ FALSE, /* \x1F */ FALSE, -+ /* */ TRUE, /* ! */ FALSE, /* " */ FALSE, /* # */ FALSE, -+ /* $ */ FALSE, /* % */ FALSE, /* & */ FALSE, /* ' */ TRUE, -+ /* ( */ TRUE, /* ) */ TRUE, /* * */ FALSE, /* + */ TRUE, -+ /* , */ TRUE, /* - */ TRUE, /* . */ TRUE, /* / */ TRUE, -+ /* 0 */ TRUE, /* 1 */ TRUE, /* 2 */ TRUE, /* 3 */ TRUE, -+ /* 4 */ TRUE, /* 5 */ TRUE, /* 6 */ TRUE, /* 7 */ TRUE, -+ /* 8 */ TRUE, /* 9 */ TRUE, /* : */ TRUE, /* ; */ FALSE, -+ /* < */ FALSE, /* = */ FALSE, /* > */ FALSE, /* ? */ TRUE, -+ /* @ */ FALSE, /* A */ TRUE, /* B */ TRUE, /* C */ TRUE, -+ /* D */ TRUE, /* E */ TRUE, /* F */ TRUE, /* G */ TRUE, -+ /* H */ TRUE, /* I */ TRUE, /* J */ TRUE, /* K */ TRUE, -+ /* L */ TRUE, /* M */ TRUE, /* N */ TRUE, /* O */ TRUE, -+ /* P */ TRUE, /* Q */ TRUE, /* R */ TRUE, /* S */ TRUE, -+ /* T */ TRUE, /* U */ TRUE, /* V */ TRUE, /* W */ TRUE, -+ /* X */ TRUE, /* Y */ TRUE, /* Z */ TRUE, /* [ */ FALSE, -+ /* \ */ FALSE, /* ] */ FALSE, /* ^ */ FALSE, /* _ */ FALSE, -+ /* ` */ FALSE, /* a */ TRUE, /* b */ TRUE, /* c */ TRUE, -+ /* d */ TRUE, /* e */ TRUE, /* f */ TRUE, /* g */ TRUE, -+ /* h */ TRUE, /* i */ TRUE, /* j */ TRUE, /* k */ TRUE, -+ /* l */ TRUE, /* m */ TRUE, /* n */ TRUE, /* o */ TRUE, -+ /* p */ TRUE, /* q */ TRUE, /* r */ TRUE, /* s */ TRUE, -+ /* t */ TRUE, /* u */ TRUE, /* v */ TRUE, /* w */ TRUE, -+ /* x */ TRUE, /* y */ TRUE, /* z */ TRUE ++ /* \0 \x01 \x02 \x03 \x04 \x05 \x06 \a */ ++ TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* \b \t \n \v \f \r \x0E \x0F */ ++ FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ++ /* \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 */ ++ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* \x18 \x19 \x1A \e \x1C \x1D \x1E \x1F */ ++ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* ! " # $ % & ' */ ++ TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ++ /* ( ) * + , - . / */ ++ TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* 0 1 2 3 4 5 6 7 */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* 8 9 : ; < = > ? */ ++ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ++ /* @ A B C D E F G */ ++ FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* H I J K L M N O */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* P Q R S T U V W */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* X Y Z [ \ ] ^ _ */ ++ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* ` a b c d e f g */ ++ FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* h i j k l m n o */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* p q r s t u v w */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* x y z */ ++ TRUE, TRUE, TRUE + }; + + return codepoint <= 'z' ? directly_encodable_table[codepoint] : FALSE; +} + +/*********************************************************************** -+ * write_to_c_string ++ * utf7_write_c + * + * Helper for utf7_wcstombs + * + * RETURNS + * TRUE on success, FALSE on error + */ -+static inline BOOL write_to_c_string(char *dst, int dstlen, int *index, char character) ++static inline BOOL utf7_write_c(char *dst, int dstlen, int *index, char character) +{ -+ if (dst) ++ if (dstlen > 0) + { + if (*index >= dstlen) + return FALSE; @@ -99,22 +100,19 @@ index 6ccb799..b412851 100644 + const WCHAR *source_end = src + srclen; + int dest_index = 0; + -+ if (!dstlen) -+ dst = NULL; -+ + while (src < source_end) + { + if (*src == '+') + { -+ if (!write_to_c_string(dst, dstlen, &dest_index, '+')) ++ if (!utf7_write_c(dst, dstlen, &dest_index, '+')) + return -1; -+ if (!write_to_c_string(dst, dstlen, &dest_index, '-')) ++ if (!utf7_write_c(dst, dstlen, &dest_index, '-')) + return -1; + src++; + } + else if (utf7_can_directly_encode(*src)) + { -+ if (!write_to_c_string(dst, dstlen, &dest_index, *src)) ++ if (!utf7_write_c(dst, dstlen, &dest_index, *src)) + return -1; + src++; + } @@ -123,7 +121,7 @@ index 6ccb799..b412851 100644 + unsigned int offset = 0; + DWORD byte_pair = 0; + -+ if (!write_to_c_string(dst, dstlen, &dest_index, '+')) ++ if (!utf7_write_c(dst, dstlen, &dest_index, '+')) + return -1; + + do @@ -132,7 +130,7 @@ index 6ccb799..b412851 100644 + offset += 16; + while (offset >= 6) + { -+ if (!write_to_c_string(dst, dstlen, &dest_index, base64_encoding_table[(byte_pair >> (offset - 6)) & 0x3F])) ++ if (!utf7_write_c(dst, dstlen, &dest_index, base64_encoding_table[(byte_pair >> (offset - 6)) & 0x3F])) + return -1; + offset -= 6; + } @@ -142,13 +140,18 @@ index 6ccb799..b412851 100644 + + if (offset) + { ++ /* Windows won't create a padded base64 character if there's not room for the - sign too */ ++ /* this is probably a bug in Windows */ ++ if (dstlen > 0 && dest_index + 1 >= dstlen) ++ return -1; ++ + byte_pair <<= (6 - offset); -+ if (!write_to_c_string(dst, dstlen, &dest_index, base64_encoding_table[byte_pair & 0x3F])) ++ if (!utf7_write_c(dst, dstlen, &dest_index, base64_encoding_table[byte_pair & 0x3F])) + return -1; + } + + /* Windows always explicitly terminates the base64 sequence even though RFC 2152 (page 3, rule 2) does not require this */ -+ if (!write_to_c_string(dst, dstlen, &dest_index, '-')) ++ if (!utf7_write_c(dst, dstlen, &dest_index, '-')) + return -1; + } + } @@ -160,16 +163,7 @@ index 6ccb799..b412851 100644 * WideCharToMultiByte (KERNEL32.@) * * Convert a Unicode character string into a multibyte string. -@@ -2209,7 +2349,7 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, - * flags [I] Mapping Flags (MB_ constants from "winnls.h"). - * src [I] Source string buffer - * srclen [I] Length of src (in WCHARs), or -1 if src is NUL terminated -- * dst [O] Destination buffer -+ * dst [O] Destination buffer, or NULL to compute the required length - * dstlen [I] Length of dst (in bytes), or 0 to compute the required length - * defchar [I] Default character to use for conversion if no exact - * conversion can be made -@@ -2266,9 +2406,8 @@ INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen, +@@ -2261,9 +2404,8 @@ INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen, SetLastError( ERROR_INVALID_FLAGS ); return 0; } diff --git a/patches/kernel32-UTF7_Support/0003-kernel32-tests-Add-tests-for-UTF-7-conversion.patch b/patches/kernel32-UTF7_Support/0003-kernel32-tests-Add-tests-for-UTF-7-conversion.patch index f14d74e4..687c5841 100644 --- a/patches/kernel32-UTF7_Support/0003-kernel32-tests-Add-tests-for-UTF-7-conversion.patch +++ b/patches/kernel32-UTF7_Support/0003-kernel32-tests-Add-tests-for-UTF-7-conversion.patch @@ -1,59 +1,31 @@ -From a771ecc9ee4a322e98b34611b2829001ba7a4a7f Mon Sep 17 00:00:00 2001 +From 3b1bc11b71d8147a69afe052eb76510f685925b2 Mon Sep 17 00:00:00 2001 From: Alex Henrie -Date: Thu, 9 Oct 2014 15:42:51 -0600 +Date: Fri, 17 Oct 2014 00:18:39 -0600 Subject: kernel32/tests: Add tests for UTF-7 conversion. --- - dlls/kernel32/tests/codepage.c | 751 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 751 insertions(+) + dlls/kernel32/tests/codepage.c | 773 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 773 insertions(+) diff --git a/dlls/kernel32/tests/codepage.c b/dlls/kernel32/tests/codepage.c -index 8423c75..2538bc7 100644 +index 8423c75..21858ed 100644 --- a/dlls/kernel32/tests/codepage.c +++ b/dlls/kernel32/tests/codepage.c -@@ -412,6 +412,755 @@ static void test_string_conversion(LPBOOL bUsedDefaultChar) +@@ -412,6 +412,776 @@ static void test_string_conversion(LPBOOL bUsedDefaultChar) ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); } -+static void test_utf7_string_conversion(void) ++static void test_utf7_encoding(void) +{ + struct utf16_to_utf7_test + { -+ WCHAR utf16[2048]; ++ WCHAR utf16[1024]; + int utf16_len; -+ char utf7[2048]; ++ char utf7[1024]; + int utf7_len; + }; + -+ struct utf16_to_utf7_test utf16_to_utf7_tests[] = { -+ /* tests which one-byte characters are base64-encoded and which are not */ -+ { -+ {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, -+ 26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, -+ 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69, -+ 70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91, -+ 92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110, -+ 111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, -+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144, -+ 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, -+ 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178, -+ 179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195, -+ 196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212, -+ 213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229, -+ 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246, -+ 247,248,249,250,251,252,253,254,255,256,0}, -+ 257, -+ "+AAEAAgADAAQABQAGAAcACA-\t\n+AAsADA-\r+AA4ADwAQABEAEgATABQAFQAWABc" -+ "AGAAZABoAGwAcAB0AHgAf- +ACEAIgAjACQAJQAm-'()+ACo-+-,-./0123456789:" -+ "+ADsAPAA9AD4-?+AEA-ABCDEFGHIJKLMNOPQRSTUVWXYZ+AFsAXABdAF4AXwBg-abc" -+ "defghijklmnopqrstuvwxyz+AHsAfAB9AH4AfwCAAIEAggCDAIQAhQCGAIcAiACJAI" -+ "oAiwCMAI0AjgCPAJAAkQCSAJMAlACVAJYAlwCYAJkAmgCbAJwAnQCeAJ8AoAChAKIA" -+ "owCkAKUApgCnAKgAqQCqAKsArACtAK4ArwCwALEAsgCzALQAtQC2ALcAuAC5ALoAuw" -+ "C8AL0AvgC/AMAAwQDCAMMAxADFAMYAxwDIAMkAygDLAMwAzQDOAM8A0ADRANIA0wDU" -+ "ANUA1gDXANgA2QDaANsA3ADdAN4A3wDgAOEA4gDjAOQA5QDmAOcA6ADpAOoA6wDsAO" -+ "0A7gDvAPAA8QDyAPMA9AD1APYA9wD4APkA+gD7APwA/QD+AP8BAA-", -+ 579 -+ }, ++ static const struct utf16_to_utf7_test utf16_to_utf7_tests[] = { + /* tests some valid UTF-16 */ + { + {0x4F60,0x597D,0x5417,0}, @@ -79,208 +51,25 @@ index 8423c75..2538bc7 100644 + } + }; + -+ struct utf7_to_utf16_test -+ { -+ char utf7[2048]; -+ WCHAR utf16[2048]; -+ int utf16_len; -+ }; -+ -+ struct utf7_to_utf16_test utf7_to_utf16_tests[] = { -+ /* tests some invalid UTF-7 */ -+ /* (number of bits in base64 sequence is not a multiple of 16 and the last bit is a 1) */ -+ /* also tests whether the unfinished byte pair is discarded or not */ -+ { -+ "+T2B-+T2B-+T2B-hello", -+ {0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, -+ 9 -+ }, -+ /* tests some more invalid UTF-7 */ -+ /* (number of bits in base64 sequence is a multiple of 8 but not a multiple of 16) */ -+ /* also tests whether the unfinished byte pair is discarded or not */ -+ { -+ "+T2BZ-+T2BZ-+T2BZ-hello", -+ {0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, -+ 9 -+ }, -+ /* tests UTF-7 followed by characters that should be encoded but aren't */ -+ { -+ "+T2BZ-\x82\xFE", -+ {0x4F60,0x0082,0x00FE,0}, -+ 4 -+ } -+ }; -+ + struct wcstombs_test + { + /* inputs */ -+ WCHAR src[2048]; ++ WCHAR src[1024]; + int srclen; + int dstlen; + /* expected outputs */ -+ char dst[2048]; ++ char dst[1024]; + int chars_written; + int len; + DWORD error; + }; + -+ struct wcstombs_test wcstombs_tests[] = { -+ /* tests which characters are encoded if surrounded by non-encoded characters */ -+ { -+ {' ',0x01,' ',0x02,' ',0x03,' ',0x04,' ',0x05,' ',0x06,' ',0x07,' ', -+ 0x08,' ',0x09,' ',0x0A,' ',0x0B,' ',0x0C,' ',0x0D,' ',0x0E,' ',0x0F, -+ ' ',0x10,' ',0x11,' ',0x12,' ',0x13,' ',0x14,' ',0x15,' ',0x16,' ', -+ 0x17,' ',0x18,' ',0x19,' ',0x1A,' ',0x1B,' ',0x1C,' ',0x1D,' ',0x1E, -+ ' ',0x1F,' ',0x20,' ',0x21,' ',0x22,' ',0x23,' ',0x24,' ',0x25,' ', -+ 0x26,' ',0x27,' ',0x28,' ',0x29,' ',0x2A,' ',0x2B,' ',0x2C,' ',0x2D, -+ ' ',0x2E,' ',0x2F,' ',0x30,' ',0x31,' ',0x32,' ',0x33,' ',0x34,' ', -+ 0x35,' ',0x36,' ',0x37,' ',0x38,' ',0x39,' ',0x3A,' ',0x3B,' ',0x3C, -+ ' ',0x3D,' ',0x3E,' ',0x3F,' ',0x40,' ',0x41,' ',0x42,' ',0x43,' ', -+ 0x44,' ',0x45,' ',0x46,' ',0x47,' ',0x48,' ',0x49,' ',0x4A,' ',0x4B, -+ ' ',0x4C,' ',0x4D,' ',0x4E,' ',0x4F,' ',0x50,' ',0x51,' ',0x52,' ', -+ 0x53,' ',0x54,' ',0x55,' ',0x56,' ',0x57,' ',0x58,' ',0x59,' ',0x5A, -+ ' ',0x5B,' ',0x5C,' ',0x5D,' ',0x5E,' ',0x5F,' ',0x60,' ',0x61,' ', -+ 0x62,' ',0x63,' ',0x64,' ',0x65,' ',0x66,' ',0x67,' ',0x68,' ',0x69, -+ ' ',0x6A,' ',0x6B,' ',0x6C,' ',0x6D,' ',0x6E,' ',0x6F,' ',0x70,' ', -+ 0x71,' ',0x72,' ',0x73,' ',0x74,' ',0x75,' ',0x76,' ',0x77,' ',0x78, -+ ' ',0x79,' ',0x7A,' ',0x7B,' ',0x7C,' ',0x7D,' ',0x7E,' ',0x7F,' ', -+ 0x80,' ',0x81,' ',0x82,' ',0x83,' ',0x84,' ',0x85,' ',0x86,' ',0x87, -+ ' ',0x88,' ',0x89,' ',0x8A,' ',0x8B,' ',0x8C,' ',0x8D,' ',0x8E,' ', -+ 0x8F,' ',0x90,' ',0x91,' ',0x92,' ',0x93,' ',0x94,' ',0x95,' ',0x96, -+ ' ',0x97,' ',0x98,' ',0x99,' ',0x9A,' ',0x9B,' ',0x9C,' ',0x9D,' ', -+ 0x9E,' ',0x9F,' ',0xA0,' ',0xA1,' ',0xA2,' ',0xA3,' ',0xA4,' ',0xA5, -+ ' ',0xA6,' ',0xA7,' ',0xA8,' ',0xA9,' ',0xAA,' ',0xAB,' ',0xAC,' ', -+ 0xAD,' ',0xAE,' ',0xAF,' ',0xB0,' ',0xB1,' ',0xB2,' ',0xB3,' ',0xB4, -+ ' ',0xB5,' ',0xB6,' ',0xB7,' ',0xB8,' ',0xB9,' ',0xBA,' ',0xBB,' ', -+ 0xBC,' ',0xBD,' ',0xBE,' ',0xBF,' ',0xC0,' ',0xC1,' ',0xC2,' ',0xC3, -+ ' ',0xC4,' ',0xC5,' ',0xC6,' ',0xC7,' ',0xC8,' ',0xC9,' ',0xCA,' ', -+ 0xCB,' ',0xCC,' ',0xCD,' ',0xCE,' ',0xCF,' ',0xD0,' ',0xD1,' ',0xD2, -+ ' ',0xD3,' ',0xD4,' ',0xD5,' ',0xD6,' ',0xD7,' ',0xD8,' ',0xD9,' ', -+ 0xDA,' ',0xDB,' ',0xDC,' ',0xDD,' ',0xDE,' ',0xDF,' ',0xE0,' ',0xE1, -+ ' ',0xE2,' ',0xE3,' ',0xE4,' ',0xE5,' ',0xE6,' ',0xE7,' ',0xE8,' ', -+ 0xE9,' ',0xEA,' ',0xEB,' ',0xEC,' ',0xED,' ',0xEE,' ',0xEF,' ',0xF0, -+ ' ',0xF1,' ',0xF2,' ',0xF3,' ',0xF4,' ',0xF5,' ',0xF6,' ',0xF7,' ', -+ 0xF8,' ',0xF9,' ',0xFA,' ',0xFB,' ',0xFC,' ',0xFD,' ',0xFE,' ',0xFF, -+ ' ',0x00,' '}, -+ 513, -+ 2047, -+ " +AAE- +AAI- +AAM- +AAQ- +AAU- +AAY- +AAc- +AAg- \t \n +AAs- +AAw-" -+ " \r +AA4- +AA8- +ABA- +ABE- +ABI- +ABM- +ABQ- +ABU- +ABY- +ABc- +A" -+ "Bg- +ABk- +ABo- +ABs- +ABw- +AB0- +AB4- +AB8- +ACE- +ACI- +ACM- " -+ "+ACQ- +ACU- +ACY- ' ( ) +ACo- +- , - . / 0 1 2 3 4 5 6 7 8 9 : +AD" -+ "s- +ADw- +AD0- +AD4- ? +AEA- A B C D E F G H I J K L M N O P Q R S" -+ " T U V W X Y Z +AFs- +AFw- +AF0- +AF4- +AF8- +AGA- a b c d e f g h" -+ " i j k l m n o p q r s t u v w x y z +AHs- +AHw- +AH0- +AH4- +AH8-" -+ " +AIA- +AIE- +AII- +AIM- +AIQ- +AIU- +AIY- +AIc- +AIg- +AIk- +AIo-" -+ " +AIs- +AIw- +AI0- +AI4- +AI8- +AJA- +AJE- +AJI- +AJM- +AJQ- +AJU-" -+ " +AJY- +AJc- +AJg- +AJk- +AJo- +AJs- +AJw- +AJ0- +AJ4- +AJ8- +AKA-" -+ " +AKE- +AKI- +AKM- +AKQ- +AKU- +AKY- +AKc- +AKg- +AKk- +AKo- +AKs-" -+ " +AKw- +AK0- +AK4- +AK8- +ALA- +ALE- +ALI- +ALM- +ALQ- +ALU- +ALY-" -+ " +ALc- +ALg- +ALk- +ALo- +ALs- +ALw- +AL0- +AL4- +AL8- +AMA- +AME-" -+ " +AMI- +AMM- +AMQ- +AMU- +AMY- +AMc- +AMg- +AMk- +AMo- +AMs- +AMw-" -+ " +AM0- +AM4- +AM8- +ANA- +ANE- +ANI- +ANM- +ANQ- +ANU- +ANY- +ANc-" -+ " +ANg- +ANk- +ANo- +ANs- +ANw- +AN0- +AN4- +AN8- +AOA- +AOE- +AOI-" -+ " +AOM- +AOQ- +AOU- +AOY- +AOc- +AOg- +AOk- +AOo- +AOs- +AOw- +AO0-" -+ " +AO4- +AO8- +APA- +APE- +API- +APM- +APQ- +APU- +APY- +APc- +APg-" -+ " +APk- +APo- +APs- +APw- +AP0- +AP4- +AP8- \0 ", -+ 1230, -+ 1230, -+ 0xdeadbeef -+ }, -+ /* tests which one-byte characters are absorbed into surrounding base64 blocks */ -+ /* (Windows always ends the base64 block when it encounters a directly encodable character) */ -+ { -+ {0x2672,0x0001,0x2672,0x0002,0x2672,0x0003,0x2672,0x0004,0x2672, -+ 0x0005,0x2672,0x0006,0x2672,0x0007,0x2672,0x0008,0x2672,0x0009, -+ 0x2672,0x000A,0x2672,0x000B,0x2672,0x000C,0x2672,0x000D,0x2672, -+ 0x000E,0x2672,0x000F,0x2672,0x0010,0x2672,0x0011,0x2672,0x0012, -+ 0x2672,0x0013,0x2672,0x0014,0x2672,0x0015,0x2672,0x0016,0x2672, -+ 0x0017,0x2672,0x0018,0x2672,0x0019,0x2672,0x001A,0x2672,0x001B, -+ 0x2672,0x001C,0x2672,0x001D,0x2672,0x001E,0x2672,0x001F,0x2672, -+ 0x0020,0x2672,0x0021,0x2672,0x0022,0x2672,0x0023,0x2672,0x0024, -+ 0x2672,0x0025,0x2672,0x0026,0x2672,0x0027,0x2672,0x0028,0x2672, -+ 0x0029,0x2672,0x002A,0x2672,0x002B,0x2672,0x002C,0x2672,0x002D, -+ 0x2672,0x002E,0x2672,0x002F,0x2672,0x0030,0x2672,0x0031,0x2672, -+ 0x0032,0x2672,0x0033,0x2672,0x0034,0x2672,0x0035,0x2672,0x0036, -+ 0x2672,0x0037,0x2672,0x0038,0x2672,0x0039,0x2672,0x003A,0x2672, -+ 0x003B,0x2672,0x003C,0x2672,0x003D,0x2672,0x003E,0x2672,0x003F, -+ 0x2672,0x0040,0x2672,0x0041,0x2672,0x0042,0x2672,0x0043,0x2672, -+ 0x0044,0x2672,0x0045,0x2672,0x0046,0x2672,0x0047,0x2672,0x0048, -+ 0x2672,0x0049,0x2672,0x004A,0x2672,0x004B,0x2672,0x004C,0x2672, -+ 0x004D,0x2672,0x004E,0x2672,0x004F,0x2672,0x0050,0x2672,0x0051, -+ 0x2672,0x0052,0x2672,0x0053,0x2672,0x0054,0x2672,0x0055,0x2672, -+ 0x0056,0x2672,0x0057,0x2672,0x0058,0x2672,0x0059,0x2672,0x005A, -+ 0x2672,0x005B,0x2672,0x005C,0x2672,0x005D,0x2672,0x005E,0x2672, -+ 0x005F,0x2672,0x0060,0x2672,0x0061,0x2672,0x0062,0x2672,0x0063, -+ 0x2672,0x0064,0x2672,0x0065,0x2672,0x0066,0x2672,0x0067,0x2672, -+ 0x0068,0x2672,0x0069,0x2672,0x006A,0x2672,0x006B,0x2672,0x006C, -+ 0x2672,0x006D,0x2672,0x006E,0x2672,0x006F,0x2672,0x0070,0x2672, -+ 0x0071,0x2672,0x0072,0x2672,0x0073,0x2672,0x0074,0x2672,0x0075, -+ 0x2672,0x0076,0x2672,0x0077,0x2672,0x0078,0x2672,0x0079,0x2672, -+ 0x007A,0x2672,0x007B,0x2672,0x007C,0x2672,0x007D,0x2672,0x007E, -+ 0x2672,0x007F,0x2672,0x0080,0x2672,0x0081,0x2672,0x0082,0x2672, -+ 0x0083,0x2672,0x0084,0x2672,0x0085,0x2672,0x0086,0x2672,0x0087, -+ 0x2672,0x0088,0x2672,0x0089,0x2672,0x008A,0x2672,0x008B,0x2672, -+ 0x008C,0x2672,0x008D,0x2672,0x008E,0x2672,0x008F,0x2672,0x0090, -+ 0x2672,0x0091,0x2672,0x0092,0x2672,0x0093,0x2672,0x0094,0x2672, -+ 0x0095,0x2672,0x0096,0x2672,0x0097,0x2672,0x0098,0x2672,0x0099, -+ 0x2672,0x009A,0x2672,0x009B,0x2672,0x009C,0x2672,0x009D,0x2672, -+ 0x009E,0x2672,0x009F,0x2672,0x00A0,0x2672,0x00A1,0x2672,0x00A2, -+ 0x2672,0x00A3,0x2672,0x00A4,0x2672,0x00A5,0x2672,0x00A6,0x2672, -+ 0x00A7,0x2672,0x00A8,0x2672,0x00A9,0x2672,0x00AA,0x2672,0x00AB, -+ 0x2672,0x00AC,0x2672,0x00AD,0x2672,0x00AE,0x2672,0x00AF,0x2672, -+ 0x00B0,0x2672,0x00B1,0x2672,0x00B2,0x2672,0x00B3,0x2672,0x00B4, -+ 0x2672,0x00B5,0x2672,0x00B6,0x2672,0x00B7,0x2672,0x00B8,0x2672, -+ 0x00B9,0x2672,0x00BA,0x2672,0x00BB,0x2672,0x00BC,0x2672,0x00BD, -+ 0x2672,0x00BE,0x2672,0x00BF,0x2672,0x00C0,0x2672,0x00C1,0x2672, -+ 0x00C2,0x2672,0x00C3,0x2672,0x00C4,0x2672,0x00C5,0x2672,0x00C6, -+ 0x2672,0x00C7,0x2672,0x00C8,0x2672,0x00C9,0x2672,0x00CA,0x2672, -+ 0x00CB,0x2672,0x00CC,0x2672,0x00CD,0x2672,0x00CE,0x2672,0x00CF, -+ 0x2672,0x00D0,0x2672,0x00D1,0x2672,0x00D2,0x2672,0x00D3,0x2672, -+ 0x00D4,0x2672,0x00D5,0x2672,0x00D6,0x2672,0x00D7,0x2672,0x00D8, -+ 0x2672,0x00D9,0x2672,0x00DA,0x2672,0x00DB,0x2672,0x00DC,0x2672, -+ 0x00DD,0x2672,0x00DE,0x2672,0x00DF,0x2672,0x00E0,0x2672,0x00E1, -+ 0x2672,0x00E2,0x2672,0x00E3,0x2672,0x00E4,0x2672,0x00E5,0x2672, -+ 0x00E6,0x2672,0x00E7,0x2672,0x00E8,0x2672,0x00E9,0x2672,0x00EA, -+ 0x2672,0x00EB,0x2672,0x00EC,0x2672,0x00ED,0x2672,0x00EE,0x2672, -+ 0x00EF,0x2672,0x00F0,0x2672,0x00F1,0x2672,0x00F2,0x2672,0x00F3, -+ 0x2672,0x00F4,0x2672,0x00F5,0x2672,0x00F6,0x2672,0x00F7,0x2672, -+ 0x00F8,0x2672,0x00F9,0x2672,0x00FA,0x2672,0x00FB,0x2672,0x00FC, -+ 0x2672,0x00FD,0x2672,0x00FE,0x2672,0x00FF,0x2672,0x0100,0x2672, -+ 0x0000,0x2672}, -+ 515, -+ 2047, -+ "+JnIAASZyAAImcgADJnIABCZyAAUmcgAGJnIAByZyAAgmcg-\t+JnI-\n+JnIACyZy" -+ "AAwmcg-\r+JnIADiZyAA8mcgAQJnIAESZyABImcgATJnIAFCZyABUmcgAWJnIAFyZy" -+ "ABgmcgAZJnIAGiZyABsmcgAcJnIAHSZyAB4mcgAfJnI- +JnIAISZyACImcgAjJnIA" -+ "JCZyACUmcgAmJnI-'+JnI-(+JnI-)+JnIAKiZy-+-+JnI-,+JnI--+JnI-.+JnI-/+" -+ "JnI-0+JnI-1+JnI-2+JnI-3+JnI-4+JnI-5+JnI-6+JnI-7+JnI-8+JnI-9+JnI-:+" -+ "JnIAOyZyADwmcgA9JnIAPiZy-?+JnIAQCZy-A+JnI-B+JnI-C+JnI-D+JnI-E+JnI-" -+ "F+JnI-G+JnI-H+JnI-I+JnI-J+JnI-K+JnI-L+JnI-M+JnI-N+JnI-O+JnI-P+JnI-" -+ "Q+JnI-R+JnI-S+JnI-T+JnI-U+JnI-V+JnI-W+JnI-X+JnI-Y+JnI-Z+JnIAWyZyAF" -+ "wmcgBdJnIAXiZyAF8mcgBgJnI-a+JnI-b+JnI-c+JnI-d+JnI-e+JnI-f+JnI-g+Jn" -+ "I-h+JnI-i+JnI-j+JnI-k+JnI-l+JnI-m+JnI-n+JnI-o+JnI-p+JnI-q+JnI-r+Jn" -+ "I-s+JnI-t+JnI-u+JnI-v+JnI-w+JnI-x+JnI-y+JnI-z+JnIAeyZyAHwmcgB9JnIA" -+ "fiZyAH8mcgCAJnIAgSZyAIImcgCDJnIAhCZyAIUmcgCGJnIAhyZyAIgmcgCJJnIAii" -+ "ZyAIsmcgCMJnIAjSZyAI4mcgCPJnIAkCZyAJEmcgCSJnIAkyZyAJQmcgCVJnIAliZy" -+ "AJcmcgCYJnIAmSZyAJomcgCbJnIAnCZyAJ0mcgCeJnIAnyZyAKAmcgChJnIAoiZyAK" -+ "MmcgCkJnIApSZyAKYmcgCnJnIAqCZyAKkmcgCqJnIAqyZyAKwmcgCtJnIAriZyAK8m" -+ "cgCwJnIAsSZyALImcgCzJnIAtCZyALUmcgC2JnIAtyZyALgmcgC5JnIAuiZyALsmcg" -+ "C8JnIAvSZyAL4mcgC/JnIAwCZyAMEmcgDCJnIAwyZyAMQmcgDFJnIAxiZyAMcmcgDI" -+ "JnIAySZyAMomcgDLJnIAzCZyAM0mcgDOJnIAzyZyANAmcgDRJnIA0iZyANMmcgDUJn" -+ "IA1SZyANYmcgDXJnIA2CZyANkmcgDaJnIA2yZyANwmcgDdJnIA3iZyAN8mcgDgJnIA" -+ "4SZyAOImcgDjJnIA5CZyAOUmcgDmJnIA5yZyAOgmcgDpJnIA6iZyAOsmcgDsJnIA7S" -+ "ZyAO4mcgDvJnIA8CZyAPEmcgDyJnIA8yZyAPQmcgD1JnIA9iZyAPcmcgD4JnIA+SZy" -+ "APomcgD7JnIA/CZyAP0mcgD+JnIA/yZyAQAmcg-\0+JnI-", -+ 1428, -+ 1428, -+ 0xdeadbeef -+ }, ++ static const struct wcstombs_test wcstombs_tests[] = { + /* tests srclen > strlenW(src) */ + { + {'a',0,'b',0}, + 4, -+ 2047, ++ 1023, + "a\0b", + 4, + 4, @@ -290,17 +79,17 @@ index 8423c75..2538bc7 100644 + { + {'h','e','l','l','o',0}, + 2, -+ 2047, ++ 1023, + "he", + 2, + 2, + 0xdeadbeef + }, -+ /* tests srclen < strlenW(src) with non-directly encodable chars*/ ++ /* tests srclen < strlenW(src) with non-directly encodable chars */ + { + {0x4F60,0x597D,0x5417,0}, + 2, -+ 2047, ++ 1023, + "+T2BZfQ-", + 8, + 8, @@ -316,176 +105,373 @@ index 8423c75..2538bc7 100644 + 0, + ERROR_INSUFFICIENT_BUFFER + }, -+ /* tests a buffer that runs out in the middle of encoding a UTF-7 sequence */ ++ /* tests a buffer that runs out after writing 1 base64 character */ + { -+ {0x4F60,0x597D,0}, ++ {0x4F60,0x0001,0}, + -1, + 2, + "+T", + 2, + 0, + ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out after writing 2 base64 characters */ ++ { ++ {0x4F60,0x0001,0}, ++ -1, ++ 3, ++ "+T2", ++ 3, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out after writing 3 base64 characters */ ++ { ++ {0x4F60,0x0001,0}, ++ -1, ++ 4, ++ "+T2A", ++ 4, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out just after writing the + sign */ ++ { ++ {0x4F60,0}, ++ -1, ++ 1, ++ "+", ++ 1, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out just before writing the - sign */ ++ /* the number of bits to encode here is not evenly divisible by 6 */ ++ { ++ {0x4F60,0}, ++ -1, ++ 4, ++ "+T2", ++ 3, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out just before writing the - sign */ ++ /* the number of bits to encode here is evenly divisible by 6 */ ++ { ++ {0x4F60,0x597D,0x5417,0}, ++ -1, ++ 9, ++ "+T2BZfVQX", ++ 9, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out in the middle of escaping a + sign */ ++ { ++ {'+',0}, ++ -1, ++ 1, ++ "+", ++ 1, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ } ++ }; ++ ++ static const BOOL directly_encodable_table[] = { ++ /* \0 \x01 \x02 \x03 \x04 \x05 \x06 \a */ ++ TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* \b \t \n \v \f \r \x0E \x0F */ ++ FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ++ /* \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 */ ++ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* \x18 \x19 \x1A \e \x1C \x1D \x1E \x1F */ ++ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* ! " # $ % & ' */ ++ TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ++ /* ( ) * + , - . / */ ++ TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* 0 1 2 3 4 5 6 7 */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* 8 9 : ; < = > ? */ ++ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ++ /* @ A B C D E F G */ ++ FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* H I J K L M N O */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* P Q R S T U V W */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* X Y Z [ \ ] ^ _ */ ++ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ++ /* ` a b c d e f g */ ++ FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* h i j k l m n o */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* p q r s t u v w */ ++ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ++ /* x y z */ ++ TRUE, TRUE, TRUE ++ }; ++ ++ static const char base64_encoding_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++ ++ int i; ++ ++ for (i = 0; i < sizeof(utf16_to_utf7_tests) / sizeof(struct utf16_to_utf7_test); i++) ++ { ++ char c_buffer[1024]; ++ WCHAR w_buffer[1024]; ++ int len; ++ ++ c_buffer[sizeof(c_buffer) - 1] = 0; ++ w_buffer[sizeof(w_buffer) / sizeof(WCHAR) - 1] = 0; ++ ++ /* test string conversion with srclen=-1 */ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ SetLastError(0xdeadbeef); ++ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, sizeof(c_buffer), NULL, NULL); ++ ok(len == utf16_to_utf7_tests[i].utf7_len && ++ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && ++ c_buffer[len] == '#', ++ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ ++ /* test string conversion with srclen=-2 */ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ SetLastError(0xdeadbeef); ++ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -2, c_buffer, sizeof(c_buffer), NULL, NULL); ++ ok(len == utf16_to_utf7_tests[i].utf7_len && ++ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && ++ c_buffer[len] == '#', ++ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ ++ /* test string conversion with dstlen=len-1 */ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ SetLastError(0xdeadbeef); ++ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, utf16_to_utf7_tests[i].utf7_len - 1, NULL, NULL); ++ ok(len == 0 && ++ memcmp(c_buffer, utf16_to_utf7_tests[i].utf7, utf16_to_utf7_tests[i].utf7_len - 1) == 0 && ++ c_buffer[utf16_to_utf7_tests[i].utf7_len - 1] == '#', ++ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); ++ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error=%x\n", GetLastError()); ++ ++ /* test string conversion with dstlen=len */ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ SetLastError(0xdeadbeef); ++ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, utf16_to_utf7_tests[i].utf7_len, NULL, NULL); ++ ok(len == utf16_to_utf7_tests[i].utf7_len && ++ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && ++ c_buffer[len] == '#', ++ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ ++ /* test string conversion with dstlen=len+1 */ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ SetLastError(0xdeadbeef); ++ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, utf16_to_utf7_tests[i].utf7_len + 1, NULL, NULL); ++ ok(len == utf16_to_utf7_tests[i].utf7_len && ++ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && ++ c_buffer[len] == '#', ++ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ ++ /* test dry run with dst=NULL and dstlen=0 */ ++ memset(c_buffer, '#', sizeof(c_buffer)); ++ SetLastError(0xdeadbeef); ++ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, NULL, 0, NULL, NULL); ++ ok(len == utf16_to_utf7_tests[i].utf7_len && ++ c_buffer[0] == '#', ++ "utf16_to_utf7_test failure i=%i len=%i\n", i, len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ ++ /* test dry run with dst!=NULL and dstlen=0 */ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ SetLastError(0xdeadbeef); ++ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, 0, NULL, NULL); ++ ok(len == utf16_to_utf7_tests[i].utf7_len && ++ c_buffer[0] == '#', ++ "utf16_to_utf7_test failure i=%i len=%i\n", i, len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ ++ /* all simple utf16-to-utf7 tests can be reversed to make utf7-to-utf16 tests */ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0xdeadbeef); ++ len = MultiByteToWideChar(CP_UTF7, 0, utf16_to_utf7_tests[i].utf7, -1, w_buffer, sizeof(w_buffer) / sizeof(WCHAR)); ++ ok(len == utf16_to_utf7_tests[i].utf16_len && ++ memcmp(w_buffer, utf16_to_utf7_tests[i].utf16, len * sizeof(WCHAR)) == 0 && ++ w_buffer[len] == 0x2323, ++ "utf16_to_utf7_test failure i=%i dst=%s len=%i\n", i, wine_dbgstr_w(w_buffer), len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ } ++ ++ for (i = 0; i < sizeof(wcstombs_tests) / sizeof(struct wcstombs_test); i++) ++ { ++ char c_buffer[1024]; ++ int len; ++ ++ c_buffer[sizeof(c_buffer) - 1] = 0; ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ SetLastError(0xdeadbeef); ++ ++ len = WideCharToMultiByte(CP_UTF7, 0, wcstombs_tests[i].src, wcstombs_tests[i].srclen, c_buffer, wcstombs_tests[i].dstlen, NULL, NULL); ++ ok(len == wcstombs_tests[i].len && ++ memcmp(c_buffer, wcstombs_tests[i].dst, wcstombs_tests[i].chars_written) == 0 && ++ c_buffer[wcstombs_tests[i].chars_written] == '#', ++ "wcstombs_test failure i=%i len=%i dst=\"%s\"\n", i, len, c_buffer); ++ ok(GetLastError() == wcstombs_tests[i].error, "error=%x\n", GetLastError()); ++ } ++ ++ /* test which characters are encoded if surrounded by non-encoded characters */ ++ for (i = 0; i <= 0xFFFF; i++) ++ { ++ WCHAR w_buffer[] = {' ',i,' ',0}; ++ char c_buffer[1024]; ++ int len; ++ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ c_buffer[sizeof(c_buffer) - 1] = 0; ++ SetLastError(0xdeadbeef); ++ ++ len = WideCharToMultiByte(CP_UTF7, 0, w_buffer, sizeof(w_buffer) / sizeof(WCHAR), c_buffer, 1023, NULL, NULL); ++ ++ if (i == '+') ++ { ++ /* escapes */ ++ ok(len == 5 && ++ memcmp(c_buffer, " +- \0#", 6) == 0, ++ "non-encoded surrounding characters failure i='+' len=%i dst=\"%s\"\n", len, c_buffer); ++ } ++ else if (i <= 'z' && directly_encodable_table[i]) ++ { ++ /* encodes directly */ ++ ok(len == 4 && ++ c_buffer[0] == ' ' && c_buffer[1] == i && memcmp(c_buffer + 2, " \0#", 3) == 0, ++ "non-encoded surrounding characters failure i=0x%04x len=%i dst=\"%s\"\n", i, len, c_buffer); ++ } ++ else ++ { ++ /* base64-encodes */ ++ ok(len == 8 && ++ memcmp(c_buffer, " +", 2) == 0 && ++ c_buffer[2] == base64_encoding_table[(i & 0xFC00) >> 10] && ++ c_buffer[3] == base64_encoding_table[(i & 0x03F0) >> 4] && ++ c_buffer[4] == base64_encoding_table[(i & 0x000F) << 2] && ++ memcmp(c_buffer + 5, "- \0#", 4) == 0, ++ "non-encoded surrounding characters failure i=0x%04x len=%i dst=\"%s\" %c\n", i, len, c_buffer, base64_encoding_table[i & 0xFC00 >> 10]); ++ } ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ } ++ ++ /* test which one-byte characters are absorbed into surrounding base64 blocks */ ++ /* (Windows always ends the base64 block when it encounters a directly encodable character) */ ++ for (i = 0; i <= 0xFFFF; i++) ++ { ++ WCHAR w_buffer[] = {0x2672,i,0x2672,0}; ++ char c_buffer[1024]; ++ int len; ++ ++ memset(c_buffer, '#', sizeof(c_buffer) - 1); ++ c_buffer[sizeof(c_buffer) - 1] = 0; ++ SetLastError(0xdeadbeef); ++ ++ len = WideCharToMultiByte(CP_UTF7, 0, w_buffer, sizeof(w_buffer) / sizeof(WCHAR), c_buffer, 1023, NULL, NULL); ++ ++ if (i == '+') ++ { ++ /* escapes */ ++ ok(len == 13 && ++ memcmp(c_buffer, "+JnI-+-+JnI-\0#", 14) == 0, ++ "encoded surrounding characters failure i='+' len=%i dst=\"%s\"\n", len, c_buffer); ++ } ++ else if (i <= 'z' && directly_encodable_table[i]) ++ { ++ /* encodes directly */ ++ ok(len == 12 && ++ memcmp(c_buffer, "+JnI-", 5) == 0 && c_buffer[5] == i && memcmp(c_buffer + 6, "+JnI-\0#", 7) == 0, ++ "encoded surrounding characters failure i=0x%04x len=%i dst=\"%s\"\n", i, len, c_buffer); ++ } ++ else ++ { ++ /* base64-encodes */ ++ ok(len == 11 && ++ memcmp(c_buffer, "+Jn", 3) == 0 && ++ c_buffer[3] == base64_encoding_table[8 | ((i & 0xC000) >> 14)] && ++ c_buffer[4] == base64_encoding_table[(i & 0x3F00) >> 8] && ++ c_buffer[5] == base64_encoding_table[(i & 0x00FC) >> 2] && ++ c_buffer[6] == base64_encoding_table[((i & 0x0003) << 4) | 2] && ++ memcmp(c_buffer + 7, "Zy-\0#", 5) == 0, ++ "encoded surrounding characters failure i=0x%04x len=%i dst=\"%s\" %c\n", i, len, c_buffer, base64_encoding_table[8 | ((i & 0xC000) >> 14)]); ++ } ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ } ++} ++ ++static void test_utf7_decoding(void) ++{ ++ struct utf7_to_utf16_test ++ { ++ char utf7[1024]; ++ WCHAR utf16[1024]; ++ int utf16_len; ++ }; ++ ++ static const struct utf7_to_utf16_test utf7_to_utf16_tests[] = { ++ /* the first 4 tests test ill-formed UTF-7 */ ++ /* they also test whether the unfinished byte pair is discarded or not */ ++ ++ /* 6 bits, not enough for a byte pair */ ++ { ++ "+T-+T-+T-hello", ++ {'h','e','l','l','o',0}, ++ 6 ++ }, ++ /* 12 bits, not enough for a byte pair */ ++ { ++ "+T2-+T2-+T2-hello", ++ {'h','e','l','l','o',0}, ++ 6 ++ }, ++ /* 18 bits, not a multiple of 16 and the last bit is a 1 */ ++ { ++ "+T2B-+T2B-+T2B-hello", ++ {0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, ++ 9 ++ }, ++ /* 24 bits, a multiple of 8 but not a multiple of 16 */ ++ { ++ "+T2BZ-+T2BZ-+T2BZ-hello", ++ {0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, ++ 9 ++ }, ++ /* tests UTF-7 followed by characters that should be encoded but aren't */ ++ { ++ "+T2BZ-\x82\xFE", ++ {0x4F60,0x0082,0x00FE,0}, ++ 4 + } + }; + + struct mbstowcs_test + { + /* inputs */ -+ char src[2048]; ++ char src[1024]; + int srclen; + int dstlen; + /* expected outputs */ -+ WCHAR dst[2048]; ++ WCHAR dst[1024]; + int chars_written; + int len; + DWORD error; + }; + -+ struct mbstowcs_test mbstowcs_tests[] = { -+ /* tests which one-byte characters implicitly terminate a sequence */ -+ /* also tests whether the unfinished byte pair is discarded or not */ -+ /* also tests srclen > strlen(src) */ -+ { -+ "+A\x01-+B\x02-+C\x03-+D\x04-+E\x05-+F\x06-+G\x07-+H\x08-+I\x09-+J" -+ "\x0A-+K\x0B-+L\x0C-+M\x0D-+N\x0E-+O\x0F-+P\x10-+Q\x11-+R\x12-+S" -+ "\x13-+T\x14-+U\x15-+V\x16-+W\x17-+X\x18-+Y\x19-+Z\x1A-+a\x1B-+b" -+ "\x1C-+c\x1D-+d\x1E-+e\x1F-+f\x20-+g\x21-+h\x22-+i\x23-+j\x24-+k" -+ "\x25-+l\x26-+m\x27-+n\x28-+o\x29-+p\x2A-+q\x2B-+r\x2C-+s\x2D-+t" -+ "\x2E-+u\x2F-+v\x30-+w\x31-+x\x32-+y\x33-+z\x34-+0\x35-+1\x36-+2" -+ "\x37-+3\x38-+4\x39-+5\x3A-+6\x3B-+7\x3C-+8\x3D-+9\x3E-++\x3F-+/" -+ "\x40-+A\x41-+B\x42-+C\x43-+D\x44-+E\x45-+F\x46-+G\x47-+H\x48-+I" -+ "\x49-+J\x4A-+K\x4B-+L\x4C-+M\x4D-+N\x4E-+O\x4F-+P\x50-+Q\x51-+R" -+ "\x52-+S\x53-+T\x54-+U\x55-+V\x56-+W\x57-+X\x58-+Y\x59-+Z\x5A-+a" -+ "\x5B-+b\x5C-+c\x5D-+d\x5E-+e\x5F-+f\x60-+g\x61-+h\x62-+i\x63-+j" -+ "\x64-+k\x65-+l\x66-+m\x67-+n\x68-+o\x69-+p\x6A-+q\x6B-+r\x6C-+s" -+ "\x6D-+t\x6E-+u\x6F-+v\x70-+w\x71-+x\x72-+y\x73-+z\x74-+0\x75-+1" -+ "\x76-+2\x77-+3\x78-+4\x79-+5\x7A-+6\x7B-+7\x7C-+8\x7D-+9\x7E-++" -+ "\x7F-+/\x80-+A\x81-+B\x82-+C\x83-+D\x84-+E\x85-+F\x86-+G\x87-+H" -+ "\x88-+I\x89-+J\x8A-+K\x8B-+L\x8C-+M\x8D-+N\x8E-+O\x8F-+P\x90-+Q" -+ "\x91-+R\x92-+S\x93-+T\x94-+U\x95-+V\x96-+W\x97-+X\x98-+Y\x99-+Z" -+ "\x9A-+a\x9B-+b\x9C-+c\x9D-+d\x9E-+e\x9F-+f\xA0-+g\xA1-+h\xA2-+i" -+ "\xA3-+j\xA4-+k\xA5-+l\xA6-+m\xA7-+n\xA8-+o\xA9-+p\xAA-+q\xAB-+r" -+ "\xAC-+s\xAD-+t\xAE-+u\xAF-+v\xB0-+w\xB1-+x\xB2-+y\xB3-+z\xB4-+0" -+ "\xB5-+1\xB6-+2\xB7-+3\xB8-+4\xB9-+5\xBA-+6\xBB-+7\xBC-+8\xBD-+9" -+ "\xBE-++\xBF-+/\xC0-+A\xC1-+B\xC2-+C\xC3-+D\xC4-+E\xC5-+F\xC6-+G" -+ "\xC7-+H\xC8-+I\xC9-+J\xCA-+K\xCB-+L\xCC-+M\xCD-+N\xCE-+O\xCF-+P" -+ "\xD0-+Q\xD1-+R\xD2-+S\xD3-+T\xD4-+U\xD5-+V\xD6-+W\xD7-+X\xD8-+Y" -+ "\xD9-+Z\xDA-+a\xDB-+b\xDC-+c\xDD-+d\xDE-+e\xDF-+f\xE0-+g\xE1-+h" -+ "\xE2-+i\xE3-+j\xE4-+k\xE5-+l\xE6-+m\xE7-+n\xE8-+o\xE9-+p\xEA-+q" -+ "\xEB-+r\xEC-+s\xED-+t\xEE-+u\xEF-+v\xF0-+w\xF1-+x\xF2-+y\xF3-+z" -+ "\xF4-+0\xF5-+1\xF6-+2\xF7-+3\xF8-+4\xF9-+5\xFA-+6\xFB-+7\xFC-+8" -+ "\xFD-+9\xFE-++\xFF-+A", -+ 1023, -+ 2047, -+ {0x0001,'-',0x0002,'-',0x0003,'-',0x0004,'-',0x0005,'-',0x0006,'-', -+ 0x0007,'-',0x0008,'-','\t','-','\n','-',0x000B,'-',0x000C,'-','\r', -+ '-',0x000E,'-',0x000F,'-',0x0010,'-',0x0011,'-',0x0012,'-',0x0013, -+ '-',0x0014,'-',0x0015,'-',0x0016,'-',0x0017,'-',0x0018,'-',0x0019, -+ '-',0x001A,'-',0x001B,'-',0x001C,'-',0x001D,'-',0x001E,'-',0x001F, -+ '-',' ','-','!','-','"','-','#','-','$','-','%','-','&','-','\'', -+ '-','(','-',')','-','*','-',',','-','-','.','-',':','-',';','-','<', -+ '-','=','-','>','-','?','-','@','-','[','-','\\','-',']','-','^', -+ '-','_','-','`','-','{','-','|','-','}','-','~','-',0x007F,'-', -+ 0x0080,'-',0x0081,'-',0xFC00,0x0082,'-',0x0083,'-',0x0084,'-', -+ 0x420C,0x0085,'-',0x0086,'-',0x4146,0x0087,'-',0x0088,'-',0x0089, -+ '-',0x1C82,0x008A,'-',0x008B,'-',0x008C,'-',0x4A2C,0x008D,'-', -+ 0x008E,'-',0xC34E,0x008F,'-',0x0090,'-',0x0091,'-',0x3D04,0x0092, -+ '-',0x0093,'-',0x0094,'-',0x524D,0x0095,'-',0x0096,'-',0x4556, -+ 0x0097,'-',0x0098,'-',0x0099,'-',0x5D86,0x009A,'-',0x009B,'-', -+ 0x009C,'-',0x5A6D,0x009D,'-',0x009E,'-',0xC75E,0x009F,'-',0x00A0, -+ '-',0x00A1,'-',0x7E08,0x00A2,'-',0x00A3,'-',0x00A4,'-',0x628E, -+ 0x00A5,'-',0x00A6,'-',0x4966,0x00A7,'-',0x00A8,'-',0x00A9,'-', -+ 0x9E8A,0x00AA,'-',0x00AB,'-',0x00AC,'-',0x6AAE,0x00AD,'-',0x00AE, -+ '-',0xCB6E,0x00AF,'-',0x00B0,'-',0x00B1,'-',0xBF0C,0x00B2,'-', -+ 0x00B3,'-',0x00B4,'-',0x72CF,0x00B5,'-',0x00B6,'-',0x4D76,0x00B7, -+ '-',0x00B8,'-',0x00B9,'-',0xDF8E,0x00BA,'-',0x00BB,'-',0x00BC,'-', -+ 0x7AEF,0x00BD,'-',0x00BE,'-',0xCF7E,0x00BF,'-',0x00C0,'-',0x00C1, -+ '-',0xFC00,0x00C2,'-',0x00C3,'-',0x00C4,'-',0x420C,0x00C5,'-', -+ 0x00C6,'-',0x4146,0x00C7,'-',0x00C8,'-',0x00C9,'-',0x1C82,0x00CA, -+ '-',0x00CB,'-',0x00CC,'-',0x4A2C,0x00CD,'-',0x00CE,'-',0xC34E, -+ 0x00CF,'-',0x00D0,'-',0x00D1,'-',0x3D04,0x00D2,'-',0x00D3,'-', -+ 0x00D4,'-',0x524D,0x00D5,'-',0x00D6,'-',0x4556,0x00D7,'-',0x00D8, -+ '-',0x00D9,'-',0x5D86,0x00DA,'-',0x00DB,'-',0x00DC,'-',0x5A6D, -+ 0x00DD,'-',0x00DE,'-',0xC75E,0x00DF,'-',0x00E0,'-',0x00E1,'-', -+ 0x7E08,0x00E2,'-',0x00E3,'-',0x00E4,'-',0x628E,0x00E5,'-',0x00E6, -+ '-',0x4966,0x00E7,'-',0x00E8,'-',0x00E9,'-',0x9E8A,0x00EA,'-', -+ 0x00EB,'-',0x00EC,'-',0x6AAE,0x00ED,'-',0x00EE,'-',0xCB6E,0x00EF, -+ '-',0x00F0,'-',0x00F1,'-',0xBF0C,0x00F2,'-',0x00F3,'-',0x00F4,'-', -+ 0x72CF,0x00F5,'-',0x00F6,'-',0x4D76,0x00F7,'-',0x00F8,'-',0x00F9, -+ '-',0xDF8E,0x00FA,'-',0x00FB,'-',0x00FC,'-',0x7AEF,0x00FD,'-', -+ 0x00FE,'-',0xCF7E,0x00FF,'-',0}, -+ 430, -+ 430, -+ 0xdeadbeef -+ }, -+ /* tests which one-byte characters remove stray + signs */ -+ { -+ "+\x01-+\x02-+\x03-+\x04-+\x05-+\x06-+\x07-+\x08-+\x09-+\x0A-+\x0B-" -+ "+\x0C-+\x0D-+\x0E-+\x0F-+\x10-+\x11-+\x12-+\x13-+\x14-+\x15-+\x16-" -+ "+\x17-+\x18-+\x19-+\x1A-+\x1B-+\x1C-+\x1D-+\x1E-+\x1F-+\x20-+\x21-" -+ "+\x22-+\x23-+\x24-+\x25-+\x26-+\x27-+\x28-+\x29-+\x2A-+\x2B-+\x2C-" -+ "+\x2D-+\x2E-+\x2F-+\x30-+\x31-+\x32-+\x33-+\x34-+\x35-+\x36-+\x37-" -+ "+\x38-+\x39-+\x3A-+\x3B-+\x3C-+\x3D-+\x3E-+\x3F-+\x40-+\x41-+\x42-" -+ "+\x43-+\x44-+\x45-+\x46-+\x47-+\x48-+\x49-+\x4A-+\x4B-+\x4C-+\x4D-" -+ "+\x4E-+\x4F-+\x50-+\x51-+\x52-+\x53-+\x54-+\x55-+\x56-+\x57-+\x58-" -+ "+\x59-+\x5A-+\x5B-+\x5C-+\x5D-+\x5E-+\x5F-+\x60-+\x61-+\x62-+\x63-" -+ "+\x64-+\x65-+\x66-+\x67-+\x68-+\x69-+\x6A-+\x6B-+\x6C-+\x6D-+\x6E-" -+ "+\x6F-+\x70-+\x71-+\x72-+\x73-+\x74-+\x75-+\x76-+\x77-+\x78-+\x79-" -+ "+\x7A-+\x7B-+\x7C-+\x7D-+\x7E-+\x7F-+\x80-+\x81-+\x82-+\x83-+\x84-" -+ "+\x85-+\x86-+\x87-+\x88-+\x89-+\x8A-+\x8B-+\x8C-+\x8D-+\x8E-+\x8F-" -+ "+\x90-+\x91-+\x92-+\x93-+\x94-+\x95-+\x96-+\x97-+\x98-+\x99-+\x9A-" -+ "+\x9B-+\x9C-+\x9D-+\x9E-+\x9F-+\xA0-+\xA1-+\xA2-+\xA3-+\xA4-+\xA5-" -+ "+\xA6-+\xA7-+\xA8-+\xA9-+\xAA-+\xAB-+\xAC-+\xAD-+\xAE-+\xAF-+\xB0-" -+ "+\xB1-+\xB2-+\xB3-+\xB4-+\xB5-+\xB6-+\xB7-+\xB8-+\xB9-+\xBA-+\xBB-" -+ "+\xBC-+\xBD-+\xBE-+\xBF-+\xC0-+\xC1-+\xC2-+\xC3-+\xC4-+\xC5-+\xC6-" -+ "+\xC7-+\xC8-+\xC9-+\xCA-+\xCB-+\xCC-+\xCD-+\xCE-+\xCF-+\xD0-+\xD1-" -+ "+\xD2-+\xD3-+\xD4-+\xD5-+\xD6-+\xD7-+\xD8-+\xD9-+\xDA-+\xDB-+\xDC-" -+ "+\xDD-+\xDE-+\xDF-+\xE0-+\xE1-+\xE2-+\xE3-+\xE4-+\xE5-+\xE6-+\xE7-" -+ "+\xE8-+\xE9-+\xEA-+\xEB-+\xEC-+\xED-+\xEE-+\xEF-+\xF0-+\xF1-+\xF2-" -+ "+\xF3-+\xF4-+\xF5-+\xF6-+\xF7-+\xF8-+\xF9-+\xFA-+\xFB-+\xFC-+\xFD-" -+ "+\xFE-+\xFF-+", -+ 767, -+ 2047, -+ {0x0001,'-',0x0002,'-',0x0003,'-',0x0004,'-',0x0005,'-',0x0006,'-', -+ 0x0007,'-',0x0008,'-','\t','-','\n','-',0x000B,'-',0x000C,'-','\r', -+ '-',0x000E,'-',0x000F,'-',0x0010,'-',0x0011,'-',0x0012,'-',0x0013, -+ '-',0x0014,'-',0x0015,'-',0x0016,'-',0x0017,'-',0x0018,'-',0x0019, -+ '-',0x001A,'-',0x001B,'-',0x001C,'-',0x001D,'-',0x001E,'-',0x001F, -+ '-',' ','-','!','-','"','-','#','-','$','-','%','-','&','-','\'', -+ '-','(','-',')','-','*','-',',','-','+','-','.','-',':','-',';','-', -+ '<','-','=','-','>','-','?','-','@','-','[','-','\\','-',']','-', -+ '^','-','_','-','`','-','{','-','|','-','}','-','~','-',0x007F,'-', -+ 0x0080,'-',0x0081,'-',0x0082,'-',0x0083,'-',0x0084,'-',0x0085,'-', -+ 0x0086,'-',0x0087,'-',0x0088,'-',0x0089,'-',0x008A,'-',0x008B,'-', -+ 0x008C,'-',0x008D,'-',0x008E,'-',0x008F,'-',0x0090,'-',0x0091,'-', -+ 0x0092,'-',0x0093,'-',0x0094,'-',0x0095,'-',0x0096,'-',0x0097,'-', -+ 0x0098,'-',0x0099,'-',0x009A,'-',0x009B,'-',0x009C,'-',0x009D,'-', -+ 0x009E,'-',0x009F,'-',0x00A0,'-',0x00A1,'-',0x00A2,'-',0x00A3,'-', -+ 0x00A4,'-',0x00A5,'-',0x00A6,'-',0x00A7,'-',0x00A8,'-',0x00A9,'-', -+ 0x00AA,'-',0x00AB,'-',0x00AC,'-',0x00AD,'-',0x00AE,'-',0x00AF,'-', -+ 0x00B0,'-',0x00B1,'-',0x00B2,'-',0x00B3,'-',0x00B4,'-',0x00B5,'-', -+ 0x00B6,'-',0x00B7,'-',0x00B8,'-',0x00B9,'-',0x00BA,'-',0x00BB,'-', -+ 0x00BC,'-',0x00BD,'-',0x00BE,'-',0x00BF,'-',0x00C0,'-',0x00C1,'-', -+ 0x00C2,'-',0x00C3,'-',0x00C4,'-',0x00C5,'-',0x00C6,'-',0x00C7,'-', -+ 0x00C8,'-',0x00C9,'-',0x00CA,'-',0x00CB,'-',0x00CC,'-',0x00CD,'-', -+ 0x00CE,'-',0x00CF,'-',0x00D0,'-',0x00D1,'-',0x00D2,'-',0x00D3,'-', -+ 0x00D4,'-',0x00D5,'-',0x00D6,'-',0x00D7,'-',0x00D8,'-',0x00D9,'-', -+ 0x00DA,'-',0x00DB,'-',0x00DC,'-',0x00DD,'-',0x00DE,'-',0x00DF,'-', -+ 0x00E0,'-',0x00E1,'-',0x00E2,'-',0x00E3,'-',0x00E4,'-',0x00E5,'-', -+ 0x00E6,'-',0x00E7,'-',0x00E8,'-',0x00E9,'-',0x00EA,'-',0x00EB,'-', -+ 0x00EC,'-',0x00ED,'-',0x00EE,'-',0x00EF,'-',0x00F0,'-',0x00F1,'-', -+ 0x00F2,'-',0x00F3,'-',0x00F4,'-',0x00F5,'-',0x00F6,'-',0x00F7,'-', -+ 0x00F8,'-',0x00F9,'-',0x00FA,'-',0x00FB,'-',0x00FC,'-',0x00FD,'-', -+ 0x00FE,'-',0x00FF,'-',0}, -+ 383, -+ 383, -+ 0xdeadbeef -+ }, ++ static const struct mbstowcs_test mbstowcs_tests[] = { + /* tests srclen > strlen(src) */ + { + "a\0b", + 4, -+ 2047, ++ 1023, + {'a',0,'b',0}, + 4, + 4, @@ -495,7 +481,7 @@ index 8423c75..2538bc7 100644 + { + "hello", + 2, -+ 2047, ++ 1023, + {'h','e'}, + 2, + 2, @@ -505,7 +491,7 @@ index 8423c75..2538bc7 100644 + { + "+T2BZfQ-", + 4, -+ 2047, ++ 1023, + {0x4F60}, + 1, + 1, @@ -515,7 +501,7 @@ index 8423c75..2538bc7 100644 + { + "hi+T2A-", + 3, -+ 2047, ++ 1023, + {'h','i'}, + 2, + 2, @@ -525,7 +511,7 @@ index 8423c75..2538bc7 100644 + { + "+T2A-hi", + 5, -+ 2047, ++ 1023, + {0x4F60}, + 1, + 1, @@ -535,7 +521,7 @@ index 8423c75..2538bc7 100644 + { + "hi+-", + 3, -+ 2047, ++ 1023, + {'h','i'}, + 2, + 2, @@ -545,7 +531,7 @@ index 8423c75..2538bc7 100644 + { + "+-hi", + 2, -+ 2047, ++ 1023, + {'+'}, + 1, + 1, @@ -555,7 +541,7 @@ index 8423c75..2538bc7 100644 + { + "+", + 1, -+ 2047, ++ 1023, + {}, + 0, + 0, @@ -583,110 +569,73 @@ index 8423c75..2538bc7 100644 + } + }; + ++ static const char base64_decoding_table[] = { ++ /* \0 \x01 \x02 \x03 \x04 \x05 \x06 \a */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* \b \t \n \v \f \r \x0E \x0F */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* \x18 \x19 \x1A \e \x1C \x1D \x1E \x1F */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* ! " # $ % & ' */ ++ -1, -1, -1, -1, -1, -1, -1, -1, ++ /* ( ) * + , - . / */ ++ -1, -1, -1, 62, -1, -1, -1, 63, ++ /* 0 1 2 3 4 5 6 7 */ ++ 52, 53, 54, 55, 56, 57, 58, 59, ++ /* 8 9 : ; < = > ? */ ++ 60, 61, -1, -1, -1, -1, -1, -1, ++ /* @ A B C D E F G */ ++ -1, 0, 1, 2, 3, 4, 5, 6, ++ /* H I J K L M N O */ ++ 7, 8, 9, 10, 11, 12, 13, 14, ++ /* P Q R S T U V W */ ++ 15, 16, 17, 18, 19, 20, 21, 22, ++ /* X Y Z [ \ ] ^ _ */ ++ 23, 24, 25, -1, -1, -1, -1, -1, ++ /* ` a b c d e f g */ ++ -1, 26, 27, 28, 29, 30, 31, 32, ++ /* h i j k l m n o */ ++ 33, 34, 35, 36, 37, 38, 39, 40, ++ /* p q r s t u v w */ ++ 41, 42, 43, 44, 45, 46, 47, 48, ++ /* x y z { | } ~ \x7F */ ++ 49, 50, 51, -1, -1, -1, -1, -1 ++ }; ++ + int i; + -+ for (i = 0; i < sizeof(utf16_to_utf7_tests) / sizeof(struct utf16_to_utf7_test); i++) -+ { -+ char c_buffer[2048]; -+ WCHAR w_buffer[2048]; -+ int len; -+ -+ /* null-terminate the buffers */ -+ c_buffer[sizeof(c_buffer) - 1] = 0; -+ w_buffer[sizeof(w_buffer) / sizeof(WCHAR) - 1] = 0; -+ -+ /* test string conversion with srclen=-1 */ -+ memset(c_buffer, '#', sizeof(c_buffer) - 1); -+ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, sizeof(c_buffer), NULL, NULL); -+ ok(len == utf16_to_utf7_tests[i].utf7_len && -+ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && -+ c_buffer[len] == '#', -+ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); -+ -+ /* test string conversion with srclen=-2 */ -+ memset(c_buffer, '#', sizeof(c_buffer) - 1); -+ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -2, c_buffer, sizeof(c_buffer), NULL, NULL); -+ ok(len == utf16_to_utf7_tests[i].utf7_len && -+ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && -+ c_buffer[len] == '#', -+ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); -+ -+ /* test string conversion with dstlen=len-1 */ -+ memset(c_buffer, '#', sizeof(c_buffer) - 1); -+ SetLastError(0); -+ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, utf16_to_utf7_tests[i].utf7_len - 1, NULL, NULL); -+ ok(len == 0 && -+ memcmp(c_buffer, utf16_to_utf7_tests[i].utf7, utf16_to_utf7_tests[i].utf7_len - 1) == 0 && -+ c_buffer[utf16_to_utf7_tests[i].utf7_len - 1] == '#', -+ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); -+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error=%x\n", GetLastError()); -+ -+ /* test string conversion with dstlen=len */ -+ memset(c_buffer, '#', sizeof(c_buffer) - 1); -+ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, utf16_to_utf7_tests[i].utf7_len, NULL, NULL); -+ ok(len == utf16_to_utf7_tests[i].utf7_len && -+ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && -+ c_buffer[len] == '#', -+ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); -+ -+ /* test string conversion with dstlen=len+1 */ -+ memset(c_buffer, '#', sizeof(c_buffer) - 1); -+ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, utf16_to_utf7_tests[i].utf7_len + 1, NULL, NULL); -+ ok(len == utf16_to_utf7_tests[i].utf7_len && -+ strcmp(c_buffer, utf16_to_utf7_tests[i].utf7) == 0 && -+ c_buffer[len] == '#', -+ "utf16_to_utf7_test failure i=%i dst=\"%s\" len=%i\n", i, c_buffer, len); -+ -+ /* test dry run with dst=NULL and dstlen=0 */ -+ memset(c_buffer, '#', sizeof(c_buffer)); -+ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, NULL, 0, NULL, NULL); -+ ok(len == utf16_to_utf7_tests[i].utf7_len && -+ c_buffer[0] == '#', -+ "utf16_to_utf7_test failure i=%i len=%i\n", i, len); -+ -+ /* test dry run with dst!=NULL and dstlen=0 */ -+ memset(c_buffer, '#', sizeof(c_buffer) - 1); -+ len = WideCharToMultiByte(CP_UTF7, 0, utf16_to_utf7_tests[i].utf16, -1, c_buffer, 0, NULL, NULL); -+ ok(len == utf16_to_utf7_tests[i].utf7_len && -+ c_buffer[0] == '#', -+ "utf16_to_utf7_test failure i=%i len=%i\n", i, len); -+ -+ /* all simple utf16-to-utf7 tests can be reversed to make utf7-to-utf16 tests */ -+ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); -+ len = MultiByteToWideChar(CP_UTF7, 0, utf16_to_utf7_tests[i].utf7, -1, w_buffer, sizeof(w_buffer) / sizeof(WCHAR)); -+ ok(len == utf16_to_utf7_tests[i].utf16_len && -+ memcmp(w_buffer, utf16_to_utf7_tests[i].utf16, len * sizeof(WCHAR)) == 0 && -+ w_buffer[len] == 0x2323, -+ "utf16_to_utf7_test failure i=%i dst=%s len=%i\n", i, wine_dbgstr_w(w_buffer), len); -+ } -+ + for (i = 0; i < sizeof(utf7_to_utf16_tests) / sizeof(struct utf7_to_utf16_test); i++) + { -+ WCHAR w_buffer[2048]; ++ WCHAR w_buffer[1024]; + int len; + -+ /* null-terminate the buffer */ + w_buffer[sizeof(w_buffer) / sizeof(WCHAR) - 1] = 0; + + /* test string conversion with srclen=-1 */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0xdeadbeef); + len = MultiByteToWideChar(CP_UTF7, 0, utf7_to_utf16_tests[i].utf7, -1, w_buffer, sizeof(w_buffer) / sizeof(WCHAR)); + ok(len == utf7_to_utf16_tests[i].utf16_len && + winetest_strcmpW(w_buffer, utf7_to_utf16_tests[i].utf16) == 0 && + w_buffer[len] == 0x2323, + "utf7_to_utf16_test failure i=%i dst=%s len=%i\n", i, wine_dbgstr_w(w_buffer), len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); + + /* test string conversion with srclen=-2 */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0xdeadbeef); + len = MultiByteToWideChar(CP_UTF7, 0, utf7_to_utf16_tests[i].utf7, -2, w_buffer, sizeof(w_buffer) / sizeof(WCHAR)); + ok(len == utf7_to_utf16_tests[i].utf16_len && + winetest_strcmpW(w_buffer, utf7_to_utf16_tests[i].utf16) == 0 && + w_buffer[len] == 0x2323, + "utf7_to_utf16_test failure i=%i dst=%s len=%i\n", i, wine_dbgstr_w(w_buffer), len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); + + /* test string conversion with dstlen=len-1 */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); -+ SetLastError(0); ++ SetLastError(0xdeadbeef); + len = MultiByteToWideChar(CP_UTF7, 0, utf7_to_utf16_tests[i].utf7, -1, w_buffer, utf7_to_utf16_tests[i].utf16_len - 1); + ok(len == 0 && + memcmp(w_buffer, utf7_to_utf16_tests[i].utf16, (utf7_to_utf16_tests[i].utf16_len - 1) * sizeof(WCHAR)) == 0 && @@ -696,65 +645,52 @@ index 8423c75..2538bc7 100644 + + /* test string conversion with dstlen=len */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0xdeadbeef); + len = MultiByteToWideChar(CP_UTF7, 0, utf7_to_utf16_tests[i].utf7, -1, w_buffer, utf7_to_utf16_tests[i].utf16_len); + ok(len == utf7_to_utf16_tests[i].utf16_len && + winetest_strcmpW(w_buffer, utf7_to_utf16_tests[i].utf16) == 0 && + w_buffer[len] == 0x2323, + "utf7_to_utf16_test failure i=%i dst=%s len=%i\n", i, wine_dbgstr_w(w_buffer), len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); + + /* test string conversion with dstlen=len+1 */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0xdeadbeef); + len = MultiByteToWideChar(CP_UTF7, 0, utf7_to_utf16_tests[i].utf7, -1, w_buffer, utf7_to_utf16_tests[i].utf16_len + 1); + ok(len == utf7_to_utf16_tests[i].utf16_len && + winetest_strcmpW(w_buffer, utf7_to_utf16_tests[i].utf16) == 0 && + w_buffer[len] == 0x2323, + "utf7_to_utf16_test failure i=%i dst=%s len=%i\n", i, wine_dbgstr_w(w_buffer), len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); + + /* test dry run with dst=NULL and dstlen=0 */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0xdeadbeef); + len = MultiByteToWideChar(CP_UTF7, 0, utf7_to_utf16_tests[i].utf7, -1, NULL, 0); + ok(len == utf7_to_utf16_tests[i].utf16_len && + w_buffer[0] == 0x2323, + "utf7_to_utf16_test failure i=%i len=%i\n", i, len); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); + + /* test dry run with dst!=NULL and dstlen=0 */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0xdeadbeef); + len = MultiByteToWideChar(CP_UTF7, 0, utf7_to_utf16_tests[i].utf7, -1, w_buffer, 0); + ok(len == utf7_to_utf16_tests[i].utf16_len && + w_buffer[0] == 0x2323, + "utf7_to_utf16_test failure i=%i len=%i\n", i, len); -+ } -+ -+ for (i = 0; i < sizeof(wcstombs_tests) / sizeof(struct wcstombs_test); i++) -+ { -+ char c_buffer[2048]; -+ int len; -+ -+ /* null-terminate the buffer */ -+ c_buffer[sizeof(c_buffer) - 1] = 0; -+ -+ /* run a complicated utf16-to-utf7 test */ -+ memset(c_buffer, '#', sizeof(c_buffer) - 1); -+ SetLastError(0xdeadbeef); -+ len = WideCharToMultiByte(CP_UTF7, 0, wcstombs_tests[i].src, wcstombs_tests[i].srclen, c_buffer, wcstombs_tests[i].dstlen, NULL, NULL); -+ ok(len == wcstombs_tests[i].len && -+ memcmp(c_buffer, wcstombs_tests[i].dst, wcstombs_tests[i].chars_written) == 0 && -+ c_buffer[wcstombs_tests[i].chars_written] == '#', -+ "wcstombs_test failure i=%i len=%i dst=\"%s\"\n", i, len, c_buffer); -+ ok(GetLastError() == wcstombs_tests[i].error, "error=%x\n", GetLastError()); ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); + } + + for (i = 0; i < sizeof(mbstowcs_tests) / sizeof(struct mbstowcs_test); i++) + { -+ WCHAR w_buffer[2048]; ++ WCHAR w_buffer[1024]; + int len; + -+ /* null-terminate the buffer */ + w_buffer[sizeof(w_buffer) / sizeof(WCHAR) - 1] = 0; -+ -+ /* run a complicated utf7-to-utf16 test */ + memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); + SetLastError(0xdeadbeef); ++ + len = MultiByteToWideChar(CP_UTF7, 0, mbstowcs_tests[i].src, mbstowcs_tests[i].srclen, w_buffer, mbstowcs_tests[i].dstlen); + ok(len == mbstowcs_tests[i].len && + memcmp(w_buffer, mbstowcs_tests[i].dst, mbstowcs_tests[i].chars_written * sizeof(WCHAR)) == 0 && @@ -762,16 +698,102 @@ index 8423c75..2538bc7 100644 + "mbstowcs_test failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); + ok(GetLastError() == mbstowcs_tests[i].error, "error=%x\n", GetLastError()); + } ++ ++ /* test which one-byte characters remove stray + signs */ ++ for (i = 0; i < 256; i++) ++ { ++ char c_buffer[] = {'+',i,'+','A','A','A',0}; ++ WCHAR w_buffer[1024]; ++ int len; ++ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ w_buffer[sizeof(w_buffer) / sizeof(WCHAR) - 1] = 0; ++ SetLastError(0xdeadbeef); ++ ++ len = MultiByteToWideChar(CP_UTF7, 0, c_buffer, sizeof(c_buffer), w_buffer, 1023); ++ ++ if (i == '-') ++ { ++ /* removes the - sign */ ++ ok(len == 3 && w_buffer[0] == '+' && w_buffer[1] == 0 && w_buffer[2] == 0 && w_buffer[3] == 0x2323, ++ "stray + removal failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); ++ } ++ else if (i < 128 && base64_decoding_table[i] != -1) ++ { ++ /* absorbs the character into the base64 sequence */ ++ ok(len == 2 && ++ w_buffer[0] == ((base64_decoding_table[i] << 10) | 0x03E0) && ++ w_buffer[1] == 0x0000 && w_buffer[2] == 0x2323, ++ "stray + removal failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); ++ } ++ else ++ { ++ /* removes the + sign */ ++ ok(len == 3 && w_buffer[0] == i && w_buffer[1] == 0 && w_buffer[2] == 0 && w_buffer[3] == 0x2323, ++ "stray + removal failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); ++ } ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ } ++ ++ /* test which one-byte characters terminate a sequence */ ++ /* also test whether the unfinished byte pair is discarded or not */ ++ for (i = 0; i < 256; i++) ++ { ++ char c_buffer[] = {'+','B',i,'+','A','A','A',0}; ++ WCHAR w_buffer[1024]; ++ int len; ++ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ w_buffer[sizeof(w_buffer) / sizeof(WCHAR) - 1] = 0; ++ SetLastError(0xdeadbeef); ++ ++ len = MultiByteToWideChar(CP_UTF7, 0, c_buffer, sizeof(c_buffer), w_buffer, 1023); ++ ++ if (i == '-') ++ { ++ /* explicitly terminates */ ++ ok(len == 2 && ++ w_buffer[0] == 0 && w_buffer[1] == 0 && w_buffer[2] == 0x2323, ++ "implicit termination failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); ++ } ++ else if (i < 128) ++ { ++ if (base64_decoding_table[i] != -1) ++ { ++ /* absorbs the character into the base64 sequence */ ++ ok(len == 3 && ++ w_buffer[0] == (0x0400 | (base64_decoding_table[i] << 4) | 0x000F) && ++ w_buffer[1] == 0x8000 && w_buffer[2] == 0 && w_buffer[3] == 0x2323, ++ "implicit termination failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); ++ } ++ else ++ { ++ /* implicitly terminates and discards the unfinished byte pair */ ++ ok(len == 3 && ++ w_buffer[0] == i && w_buffer[1] == 0 && w_buffer[2] == 0 && w_buffer[3] == 0x2323, ++ "implicit termination failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); ++ } ++ } ++ else ++ { ++ /* implicitly terminates but does not the discard unfinished byte pair */ ++ ok(len == 3 && ++ w_buffer[0] == i && w_buffer[1] == 0x0400 && w_buffer[2] == 0 && w_buffer[3] == 0x2323, ++ "implicit termination failure i=%i len=%i dst=%s\n", i, len, wine_dbgstr_w(w_buffer)); ++ } ++ ok(GetLastError() == 0xdeadbeef, "error=%x\n", GetLastError()); ++ } +} + static void test_undefined_byte_char(void) { static const struct tag_testset { -@@ -618,6 +1367,8 @@ START_TEST(codepage) +@@ -618,6 +1388,9 @@ START_TEST(codepage) test_string_conversion(NULL); test_string_conversion(&bUsedDefaultChar); -+ test_utf7_string_conversion(); ++ test_utf7_encoding(); ++ test_utf7_decoding(); + test_undefined_byte_char(); test_threadcp(); diff --git a/patches/kernel32-UTF7_Support/definition b/patches/kernel32-UTF7_Support/definition index 3e47da53..6510aee6 100644 --- a/patches/kernel32-UTF7_Support/definition +++ b/patches/kernel32-UTF7_Support/definition @@ -1,4 +1,4 @@ Author: Alex Henrie Subject: Support for UTF7 encoding/decoding -Revision: 2 +Revision: 3 Fixes: [27388] Support for UTF7 encoding/decoding