diff --git a/README.md b/README.md index 1ca76028..20527c6e 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,11 @@ Wine. All those differences are also documented on the Included bugfixes and improvements ================================== -**Bugfixes and features included in the next upcoming release [3]:** +**Bugfixes and features included in the next upcoming release [4]:** * Anno 1602 installer depends on Windows 98 behavior of SHFileOperationW * FEAR 1 installer expects basic_string_wchar_dtor to return NULL ([Wine Bug #37358](http://bugs.winehq.org/show_bug.cgi?id=37358)) +* Support for UTF7 encoding/decoding ([Wine Bug #27388](http://bugs.winehq.org/show_bug.cgi?id=27388)) * Wine ignores IDF_CHECKFIRST flag in SetupPromptForDisk ([Wine Bug #20465](http://bugs.winehq.org/show_bug.cgi?id=20465)) diff --git a/debian/changelog b/debian/changelog index e644bf0c..b279c174 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,8 @@ wine-compholio (1.7.29) UNRELEASED; urgency=low * Updated DOS Attributes patch to better detect XATTR functions. * Added patch to support IDF_CHECKFIRST in SetupPromptForDisk. * Added patch to fix issues when executing pages with guard page / write watch permissions. + * Added patch to set return value of basic_string_wchar_dtor to return NULL. + * Added patch for UTF7 encoding/decoding support. * Removed patch to fix issues with drag image in ImageLists (accepted upstream). * Removed patch to set ldr.EntryPoint for main executable (accepted upstream). * Removed patch to implement stubs for [Get|Set]SystemFileCacheSize (accepted upstream). diff --git a/patches/Makefile b/patches/Makefile index ebf22ac7..5eb8c83a 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -36,6 +36,7 @@ PATCHLIST := \ kernel32-GetSystemTimes.ok \ kernel32-GetVolumePathName.ok \ kernel32-Named_Pipe.ok \ + kernel32-UTF7_Support.ok \ libs-Unicode_Collation.ok \ msvcp60-basic_string_wchar_dtor.ok \ ntdll-ATL_Thunk.ok \ @@ -482,6 +483,26 @@ kernel32-Named_Pipe.ok: echo '+ { "kernel32-Named_Pipe", "Dan Kegel", "Fix for ConnectNamedPort return value in overlapped mode." },'; \ ) > kernel32-Named_Pipe.ok +# Patchset kernel32-UTF7_Support +# | +# | Included patches: +# | * Support for UTF7 encoding/decoding [by Alex Henrie] +# | +# | This patchset fixes the following Wine bugs: +# | * [#27388] Support for UTF7 encoding/decoding +# | +# | Modified files: +# | * dlls/kernel32/locale.c, dlls/kernel32/tests/codepage.c +# | +.INTERMEDIATE: kernel32-UTF7_Support.ok +kernel32-UTF7_Support.ok: + $(call APPLY_FILE,kernel32-UTF7_Support/0001-kernel32-Support-UTF-7-in-MultiByteToWideChar.patch) + $(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" },'; \ + ) > kernel32-UTF7_Support.ok + # Patchset libs-Unicode_Collation # | # | Included patches: 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 new file mode 100644 index 00000000..1114ee86 --- /dev/null +++ b/patches/kernel32-UTF7_Support/0001-kernel32-Support-UTF-7-in-MultiByteToWideChar.patch @@ -0,0 +1,198 @@ +From 87874c02de939388405ebfcb752918c1a764a516 Mon Sep 17 00:00:00 2001 +From: Alex Henrie +Date: Wed, 8 Oct 2014 21:16:37 -0600 +Subject: kernel32: Support UTF-7 in MultiByteToWideChar. + +--- + dlls/kernel32/locale.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 157 insertions(+), 4 deletions(-) + +diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c +index 730574b..a5d4403 100644 +--- a/dlls/kernel32/locale.c ++++ b/dlls/kernel32/locale.c +@@ -1954,6 +1954,160 @@ BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD fla + + + /*********************************************************************** ++ * write_to_w_string ++ * ++ * 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) ++{ ++ if (dst) ++ { ++ if (*index >= dstlen) ++ return FALSE; ++ ++ dst[*index] = character; ++ } ++ ++ (*index)++; ++ ++ return TRUE; ++} ++ ++/*********************************************************************** ++ * utf7_mbstowcs ++ * ++ * UTF-7 to UTF-16 string conversion, helper for MultiByteToWideChar ++ * ++ * RETURNS ++ * On success, the number of characters written ++ * On dst buffer overflow, -1 ++ */ ++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 ++ }; ++ ++ const char *source_end = src + srclen; ++ int dest_index = 0; ++ ++ DWORD byte_pair = 0; ++ short offset = 0; ++ ++ /* MultiByteToWideChar guarantees that srclen > 0 */ ++ assert(srclen > 0); ++ ++ if (!dstlen) ++ dst = NULL; ++ ++ do ++ { ++ if (*src == '+') ++ { ++ src++; /* skip the + sign */ ++ ++ if (*src == '-') ++ { ++ /* just a plus sign escaped as +- */ ++ if (!write_to_w_string(dst, dstlen, &dest_index, '+')) ++ return -1; ++ src++; ++ continue; ++ } ++ ++ do ++ { ++ WCHAR sextet = *src; ++ if (sextet == '-') ++ { ++ /* skip over the dash and end base64 decoding */ ++ /* the current, unfinished byte pair is discarded */ ++ src++; ++ offset = 0; ++ break; ++ } ++ else if (sextet <= 127) ++ { ++ 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 current, unfinished byte pair is NOT discarded in this case */ ++ /* this is probably a bug in Windows */ ++ 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 )) ++ return -1; ++ offset -= 16; ++ } ++ ++ /* this sextet is done */ ++ src++; ++ } 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)) ++ return -1; ++ src++; ++ } ++ } while (src < source_end); ++ ++ return dest_index; ++} ++ ++/*********************************************************************** + * MultiByteToWideChar (KERNEL32.@) + * + * Convert a multibyte character string into a Unicode string. +@@ -1963,7 +2117,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 +2160,8 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, + SetLastError( ERROR_INVALID_FLAGS ); + return 0; + } +- FIXME("UTF-7 not supported\n"); +- SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); +- return 0; ++ ret = utf7_mbstowcs( src, srclen, dst, dstlen ); ++ break; + case CP_UNIXCP: + if (unix_cptable) + { +-- +2.1.2 + 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 new file mode 100644 index 00000000..f81a97da --- /dev/null +++ b/patches/kernel32-UTF7_Support/0002-kernel32-Support-UTF-7-in-WideCharToMultiByte.patch @@ -0,0 +1,183 @@ +From eb7a37bf7d71cfa8696185047483fbe02d01a5d1 Mon Sep 17 00:00:00 2001 +From: Alex Henrie +Date: Wed, 8 Oct 2014 21:18:22 -0600 +Subject: kernel32: Support UTF-7 in WideCharToMultiByte. + +--- + dlls/kernel32/locale.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 142 insertions(+), 4 deletions(-) + +diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c +index a5d4403..fc0a7ad 100644 +--- a/dlls/kernel32/locale.c ++++ b/dlls/kernel32/locale.c +@@ -2201,6 +2201,145 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen, + + + /*********************************************************************** ++ * 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 ++ }; ++ ++ return codepoint <= 'z' ? directly_encodable_table[codepoint] : FALSE; ++} ++ ++/*********************************************************************** ++ * write_to_c_string ++ * ++ * 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) ++{ ++ if (dst) ++ { ++ if (*index >= dstlen) ++ return FALSE; ++ ++ dst[*index] = character; ++ } ++ ++ (*index)++; ++ ++ return TRUE; ++} ++ ++/*********************************************************************** ++ * utf7_wcstombs ++ * ++ * UTF-16 to UTF-7 string conversion, helper for WideCharToMultiByte ++ * ++ * RETURNS ++ * On success, the number of characters written ++ * On dst buffer overflow, -1 ++ */ ++static int utf7_wcstombs(const WCHAR *src, int srclen, char *dst, int dstlen) ++{ ++ static const char base64_encoding_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++ ++ 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, '+')) ++ return -1; ++ if (!write_to_c_string(dst, dstlen, &dest_index, '-')) ++ return -1; ++ src++; ++ } ++ else if (utf7_can_directly_encode(*src)) ++ { ++ if (!write_to_c_string(dst, dstlen, &dest_index, *src)) ++ return -1; ++ src++; ++ } ++ else ++ { ++ unsigned int offset = 0; ++ DWORD byte_pair = 0; ++ ++ if (!write_to_c_string(dst, dstlen, &dest_index, '+')) ++ return -1; ++ ++ while (src < source_end && !utf7_can_directly_encode(*src)) ++ { ++ byte_pair = (byte_pair << 16) | *src; ++ offset += 16; ++ while (offset >= 6) ++ { ++ if (!write_to_c_string(dst, dstlen, &dest_index, base64_encoding_table[(byte_pair >> (offset - 6)) & 0x3F])) ++ return -1; ++ offset -= 6; ++ } ++ src++; ++ } ++ ++ if (offset) ++ { ++ byte_pair <<= (6 - offset); ++ if (!write_to_c_string(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, '-')) ++ return -1; ++ } ++ } ++ ++ return dest_index; ++} ++ ++/*********************************************************************** + * WideCharToMultiByte (KERNEL32.@) + * + * Convert a Unicode character string into a multibyte string. +@@ -2210,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 +@@ -2267,9 +2406,8 @@ INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen, + SetLastError( ERROR_INVALID_FLAGS ); + return 0; + } +- FIXME("UTF-7 not supported\n"); +- SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); +- return 0; ++ ret = utf7_wcstombs( src, srclen, dst, dstlen ); ++ break; + case CP_UNIXCP: + if (unix_cptable) + { +-- +2.1.2 + 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 new file mode 100644 index 00000000..0be617fc --- /dev/null +++ b/patches/kernel32-UTF7_Support/0003-kernel32-tests-Add-tests-for-UTF-7-conversion.patch @@ -0,0 +1,717 @@ +From 2197e9d68f4400b5c30fbbe787ac308bc8a94908 Mon Sep 17 00:00:00 2001 +From: Alex Henrie +Date: Wed, 8 Oct 2014 19:52:55 -0600 +Subject: kernel32/tests: Add tests for UTF-7 conversion. + +--- + dlls/kernel32/tests/codepage.c | 687 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 687 insertions(+) + +diff --git a/dlls/kernel32/tests/codepage.c b/dlls/kernel32/tests/codepage.c +index 8423c75..aeca011 100644 +--- a/dlls/kernel32/tests/codepage.c ++++ b/dlls/kernel32/tests/codepage.c +@@ -412,6 +412,691 @@ static void test_string_conversion(LPBOOL bUsedDefaultChar) + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + } + ++static void test_utf7_string_conversion(void) ++{ ++ struct utf16_to_utf7_test ++ { ++ WCHAR utf16[32]; ++ int utf16_len; ++ char utf7[32]; ++ int utf7_len; ++ }; ++ ++ struct utf16_to_utf7_test utf16_to_utf7_tests[] = { ++ /* test some valid UTF-16 */ ++ { ++ {0x4F60,0x597D,0x5417,0}, ++ 4, ++ "+T2BZfVQX-", ++ 11 ++ }, ++ /* tests some invalid UTF-16 */ ++ /* (stray lead surrogate) */ ++ { ++ {0xD801,0}, ++ 2, ++ "+2AE-", ++ 6 ++ }, ++ /* tests some more invalid UTF-16 */ ++ /* (codepoint does not exist) */ ++ { ++ {0xFF00,0}, ++ 2, ++ "+/wA-", ++ 6 ++ } ++ }; ++ ++ struct utf7_to_utf16_test ++ { ++ char utf7[32]; ++ WCHAR utf16[32]; ++ 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]; ++ int srclen; ++ int dstlen; ++ /* expected outputs */ ++ char dst[2048]; ++ int len; ++ DWORD error; ++ }; ++ ++ struct wcstombs_test wcstombs_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, ++ 2047, ++ "+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, ++ 0xdeadbeef ++ }, ++ /* same as above but surrounding the chars with a non-encoded char */ ++ { ++ {' ',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, ++ 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, ++ 0xdeadbeef ++ }, ++ /* tests srclen > strlenW(src) */ ++ { ++ {'a',0,'b',0}, ++ 4, ++ 2047, ++ "a\0b", ++ 4, ++ 0xdeadbeef ++ }, ++ /* tests srclen < strlenW(src) with directly encodable chars */ ++ { ++ {'h','e','l','l','o',0}, ++ 2, ++ 2047, ++ "he", ++ 2, ++ 0xdeadbeef ++ }, ++ /* tests srclen < strlenW(src) with non-directly encodable chars*/ ++ { ++ {0x4F60,0x597D,0x5417,0}, ++ 2, ++ 2047, ++ "+T2BZfQ-", ++ 8, ++ 0xdeadbeef ++ }, ++ /* tests a buffer that runs out while not encoding a UTF-7 sequence */ ++ { ++ {'h','e','l','l','o',0}, ++ -1, ++ 2, ++ "he", ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out in the middle of encoding a UTF-7 sequence */ ++ { ++ {0x4F60,0x597D,0}, ++ -1, ++ 2, ++ "+T", ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ } ++ }; ++ ++ struct mbstowcs_test ++ { ++ /* inputs */ ++ char src[2048]; ++ int srclen; ++ int dstlen; ++ /* expected outputs */ ++ WCHAR dst[2048]; ++ 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, ++ 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, ++ 0xdeadbeef ++ }, ++ /* tests srclen > strlen(src) */ ++ { ++ "a\0b", ++ 4, ++ 2047, ++ {'a',0,'b',0}, ++ 4, ++ 0xdeadbeef ++ }, ++ /* tests srclen < strlen(src) outside of a UTF-7 sequence */ ++ { ++ "hello", ++ 2, ++ 2047, ++ {'h','e'}, ++ 2, ++ 0xdeadbeef ++ }, ++ /* tests srclen < strlen(src) inside of a UTF-7 sequence */ ++ { ++ "+T2BZfQ-", ++ 4, ++ 2047, ++ {0x4F60}, ++ 1, ++ 0xdeadbeef ++ }, ++ /* tests a buffer that runs out while not decoding a UTF-7 sequence */ ++ { ++ "hello", ++ -1, ++ 2, ++ {'h','e'}, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ }, ++ /* tests a buffer that runs out in the middle of decoding a UTF-7 sequence */ ++ { ++ "+T2BZfQ-", ++ -1, ++ 1, ++ {0x4F60}, ++ 0, ++ ERROR_INSUFFICIENT_BUFFER ++ } ++ }; ++ ++ int i; ++ ++ for (i = 0; i < sizeof(utf16_to_utf7_tests) / sizeof(struct utf16_to_utf7_test); i++) ++ { ++ char c_buffer[32]; ++ WCHAR w_buffer[32]; ++ 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[32]; ++ 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)); ++ 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); ++ ++ /* test string conversion with srclen=-2 */ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ 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); ++ ++ /* test string conversion with dstlen=len-1 */ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ SetLastError(0); ++ 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 && ++ w_buffer[utf7_to_utf16_tests[i].utf16_len - 1] == 0x2323, ++ "utf7_to_utf16_test failure i=%i dst=%s len=%i\n", i, wine_dbgstr_w(w_buffer), len); ++ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error=%x\n", GetLastError()); ++ ++ /* test string conversion with dstlen=len */ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ 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); ++ ++ /* test string conversion with dstlen=len+1 */ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ 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); ++ ++ /* test dry run with dst=NULL and dstlen=0 */ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ 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); ++ ++ /* test dry run with dst!=NULL and dstlen=0 */ ++ memset(w_buffer, '#', sizeof(w_buffer) - sizeof(WCHAR)); ++ 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, len ? len : wcstombs_tests[i].dstlen) == 0 && ++ c_buffer[len ? len : wcstombs_tests[i].dstlen] == '#', ++ "wcstombs_test failure i=%i len=%i dst=\"%s\"\n", i, len, c_buffer); ++ ok(GetLastError() == wcstombs_tests[i].error, "error=%x\n", GetLastError()); ++ } ++ ++ for (i = 0; i < sizeof(mbstowcs_tests) / sizeof(struct mbstowcs_test); i++) ++ { ++ WCHAR w_buffer[2048]; ++ 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, (len ? len : mbstowcs_tests[i].dstlen) * sizeof(WCHAR)) == 0 && ++ w_buffer[len ? len : mbstowcs_tests[i].dstlen] == 0x2323, ++ "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()); ++ } ++} ++ + static void test_undefined_byte_char(void) + { + static const struct tag_testset { +@@ -618,6 +1303,8 @@ START_TEST(codepage) + test_string_conversion(NULL); + test_string_conversion(&bUsedDefaultChar); + ++ test_utf7_string_conversion(); ++ + test_undefined_byte_char(); + test_threadcp(); + } +-- +2.1.2 + diff --git a/patches/kernel32-UTF7_Support/definition b/patches/kernel32-UTF7_Support/definition new file mode 100644 index 00000000..50cc7fe0 --- /dev/null +++ b/patches/kernel32-UTF7_Support/definition @@ -0,0 +1,4 @@ +Author: Alex Henrie +Subject: Support for UTF7 encoding/decoding +Revision: 1 +Fixes: [27388] Support for UTF7 encoding/decoding