kernel32: Add UTF-7 support. (try 2)
Alex Henrie
alexhenrie24 at gmail.com
Mon Jul 30 00:38:45 CDT 2012
Fixes bug 27388.
As requested, try 2 puts everything in kernel32, does not use malloc,
and has more tests. The new tests exposed a couple of mistakes which
are now fixed.
---
dlls/kernel32/locale.c | 524 +++++++++++++++++++++++++++++++++++++++-
dlls/kernel32/tests/codepage.c | 126 ++++++++++
2 files changed, 642 insertions(+), 8 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 90603f2..32f2ee6 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -1869,6 +1869,252 @@ BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD fla
/***********************************************************************
+ * write_to_w_string
+ *
+ * Helper for utf7_mbstowcs
+ *
+ * RETURNS
+ * 0 on success, -1 on error
+ */
+static int write_to_w_string(WCHAR* dst, int dstlen, int* index, WCHAR character)
+{
+ if (*index >= dstlen)
+ {
+ return -1;
+ }
+
+ dst[*index] = character;
+ (*index)++;
+ return 0;
+}
+
+/***********************************************************************
+ * 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
+ * On invalid input char, -2
+ */
+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
+ };
+
+ BOOL dry_run = !dst || !dstlen;
+ int source_index = 0;
+ int dest_index = 0;
+
+ do
+ {
+ if (src[source_index] == 0 && srclen == -1)
+ {
+ if (dry_run) dest_index++; else if (write_to_w_string(dst, dstlen, &dest_index, 0)) return -1;
+ /* when srclen=-1, terminate at the first null character found */
+ break;
+ }
+ else if (src[source_index] == '+')
+ {
+ WCHAR byte_pair = 0;
+ short offset = 0;
+
+ source_index++; /* skip the + sign */
+
+ if (src[source_index] == '-')
+ {
+ /* just a plus sign escaped as +- */
+ if (dry_run) dest_index++; else if (write_to_w_string(dst, dstlen, &dest_index, '+')) return -1;
+ source_index++;
+ continue;
+ }
+
+ for (;;)
+ {
+ WCHAR sextet = src[source_index];
+ if (sextet == '-')
+ {
+ /* skip over the - and signal end of base64 decoding */
+ source_index++;
+ sextet = -1;
+ }
+ else if (sextet <= 'z')
+ {
+ sextet = base64_decoding_table[sextet];
+ }
+ else
+ {
+ sextet = -1;
+ }
+
+ 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 */
+ break;
+ }
+
+ if (offset > 0)
+ {
+ byte_pair |= (sextet << 10) >> offset;
+ }
+ else
+ {
+ byte_pair |= sextet << (10 - offset);
+ }
+ offset += 6;
+ if (offset > 15)
+ {
+ /* this byte pair is done */
+ if (dry_run) dest_index++; else if (write_to_w_string(dst, dstlen, &dest_index, byte_pair)) return -1;
+ byte_pair = 0;
+ /* back up the offset to begin writing to the next byte pair,
+ including writing any part of the current sextet that didn't fit in the last byte pair */
+ offset -= 22;
+ }
+ else
+ {
+ /* this sextet is done */
+ source_index++;
+ }
+ }
+ }
+ else
+ {
+ if (dry_run) dest_index++; else if (write_to_w_string(dst, dstlen, &dest_index, src[source_index])) return -1;
+ source_index++;
+ }
+ } while (srclen == -1 || source_index < srclen);
+
+ return dest_index;
+}
+
+/***********************************************************************
* MultiByteToWideChar (KERNEL32.@)
*
* Convert a multibyte character string into a Unicode string.
@@ -1878,7 +2124,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
@@ -1921,9 +2167,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)
{
@@ -1963,6 +2208,270 @@ INT WINAPI MultiByteToWideChar( UINT page, DWORD flags, LPCSTR src, INT srclen,
/***********************************************************************
+ * can_directly_encode
+ *
+ * Helper for utf7_wcstombs
+ */
+static BOOL utf7_can_directly_encode(WCHAR codepoint)
+{
+ static const BOOL directly_encodable_ascii[] = {
+ /* \0 */ TRUE, /* special case */
+ /* \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, /* special case */
+ /* , */ 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,
+ /* { */ FALSE,
+ /* | */ FALSE,
+ /* } */ FALSE,
+ /* ~ */ FALSE
+ };
+
+ if (codepoint <= '~')
+ {
+ return directly_encodable_ascii[codepoint];
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+/***********************************************************************
+ * write_to_c_string
+ *
+ * Helper for utf7_wcstombs
+ *
+ * RETURNS
+ * 0 on success, -1 on error
+ */
+static int write_to_c_string(char* dst, int dstlen, int* index, char character)
+{
+ if (*index >= dstlen)
+ {
+ return -1;
+ }
+
+ dst[*index] = character;
+ (*index)++;
+ return 0;
+}
+
+/***********************************************************************
+ * 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
+ * On invalid input char, -2
+ */
+static int utf7_wcstombs(const WCHAR* src, int srclen, char* dst, int dstlen)
+{
+ static const char base64_encoding_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ BOOL dry_run = !dst || !dstlen;
+ int source_index = 0;
+ int dest_index = 0;
+
+ do
+ {
+ if (src[source_index] == 0 && srclen == -1)
+ {
+ /* when srclen=-1, terminate at the first null character found */
+ if (dry_run) dest_index++; else if (write_to_c_string(dst, dstlen, &dest_index, 0)) return -1;
+ break;
+ }
+ else if (src[source_index] == '+')
+ {
+ if (dry_run)
+ {
+ dest_index += 2;
+ }
+ else
+ {
+ if (write_to_c_string(dst, dstlen, &dest_index, '+')) return -1;
+ if (write_to_c_string(dst, dstlen, &dest_index, '-')) return -1;
+ }
+ source_index++;
+ }
+ else if (utf7_can_directly_encode(src[source_index]))
+ {
+ if (dry_run) dest_index++; else if (write_to_c_string(dst, dstlen, &dest_index, src[source_index])) return -1;
+ source_index++;
+ }
+ else
+ {
+ unsigned int offset;
+ WCHAR char1;
+ WCHAR char2;
+
+ offset = 16;
+ char2 = src[source_index];
+ source_index++;
+
+ if (dry_run) dest_index++; else if (write_to_c_string(dst, dstlen, &dest_index, '+')) return -1;
+
+ for (;;)
+ {
+ unsigned int chars_back_to_back;
+
+ if (offset > 15)
+ {
+ if (char2 == 0)
+ {
+ /* signal to end; the next character of src is directly encodable */
+ break;
+ }
+ char1 = char2;
+ if (utf7_can_directly_encode(src[source_index]))
+ {
+ /* do not include the next character of src in the base64 sequence */
+ /* pad the bits of the last character to be encoded with zeroes if needed */
+ char2 = 0;
+ }
+ else
+ {
+ /* claim the next character for inclusion in the base64 sequence */
+ char2 = src[source_index];
+ source_index++;
+ }
+ offset -= 16;
+ }
+
+ chars_back_to_back = ((unsigned int)char1 << 16) | (unsigned int)char2;
+ if (dry_run) dest_index++; else if (write_to_c_string(dst, dstlen, &dest_index, base64_encoding_table[(chars_back_to_back << offset) >> 26])) return -1;
+ offset += 6;
+ }
+
+ /* Windows always explicitly terminates the base64 sequence even though RFC 2152 (page 3, rule 2) does not require this */
+ if (dry_run) dest_index++; else if (write_to_c_string(dst, dstlen, &dest_index, '-')) return -1;
+ }
+ }
+ while (srclen == -1 || source_index < srclen);
+
+ return dest_index;
+}
+
+/***********************************************************************
* WideCharToMultiByte (KERNEL32.@)
*
* Convert a Unicode character string into a multibyte string.
@@ -1972,7 +2481,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
@@ -2029,9 +2538,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)
{
diff --git a/dlls/kernel32/tests/codepage.c b/dlls/kernel32/tests/codepage.c
index c980348..3047eeb 100644
--- a/dlls/kernel32/tests/codepage.c
+++ b/dlls/kernel32/tests/codepage.c
@@ -412,6 +412,130 @@ static void test_string_conversion(LPBOOL bUsedDefaultChar)
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
}
+static void test_utf7_string_conversion(void)
+{
+ /* tests which ASCII characters are base64-encoded and which are not */
+ WCHAR example_0_utf16[] = {'\t',' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.',
+ '/','0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
+ '@','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','[','\\',']','^','_','`','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','{','|','}','~',0};
+ int example_0_utf16_len = sizeof(example_0_utf16) / sizeof(WCHAR);
+ char example_0_utf7[] = "\t +ACEAIgAjACQAJQAm-'()+ACo-+-,-./0123456789:+ADsAPAA9AD4-?+AEA-ABCDEFGHIJKLMNOPQRSTUVWXYZ+AFsAXABdAF4AXwBg-abcdefghijklmnopqrstuvwxyz+AHsAfAB9AH4-";
+ int example_0_utf7_len = sizeof(example_0_utf7);
+
+ /* this string is the Unicode for "5 + (<ALPHA>+<BETA>+x) <NOT EQUAL TO> <ALPHA><BETA>"
+ it tests:
+ - a + before a non-base64 character
+ - a + between two non-directly-encodable characters
+ - a + before a base64 character */
+ WCHAR example_1_utf16[] = {'5',' ','+',' ','(',0x0391,'+',0x0392,'+','x',')',' ',0x2260,' ',0x0391,0x0392,0};
+ int example_1_utf16_len = sizeof(example_1_utf16) / sizeof(WCHAR);
+ char example_1_utf7[] = "5 +- (+A5E-+-+A5I-+-x) +ImA- +A5EDkg-";
+ int example_1_utf7_len = sizeof(example_1_utf7);
+
+ /* tests a null char before the end of the buffer */
+ WCHAR example_2_utf16[] = {'a',0,'b',0};
+ int example_2_utf16_len = sizeof(example_2_utf16) / sizeof(WCHAR);
+ char example_2_utf7[] = "a\0b";
+ int example_2_utf7_len = sizeof(example_2_utf7);
+
+ /* tests some invalid UTF-7 */
+ /* (number of bits in base64 sequence is not a multiple of 16 and the last bit is a 1) */
+ char example_3_utf7[] = "+T2B-hello";
+ WCHAR example_3_utf16[] = {0x4F60,'h','e','l','l','o',0};
+ int example_3_utf16_len = sizeof(example_3_utf16) / sizeof(WCHAR);
+
+ /* tests some more invalid UTF-7 */
+ /* (number of bits in base64 sequence is a multiple of 8 but not a multiple of 16) */
+ char example_4_utf7[] = "+T2BZ-hello";
+ WCHAR example_4_utf16[] = {0x4F60,'h','e','l','l','o',0};
+ int example_4_utf16_len = sizeof(example_3_utf16) / sizeof(WCHAR);
+
+ /* tests a buffer that is too small */
+ WCHAR example_5_utf16[] = {'h','e','l','l','o',0};
+ char example_5_utf7[] = "he";
+
+ /* tests a buffer that is too small */
+ char example_6_utf7[] = "hello";
+ WCHAR example_6_utf16[] = {'h','e',0};
+
+ /* tests a buffer that runs out in the middle of encoding a UTF-7 sequence */
+ WCHAR example_7_utf16[] = {0x4F60,0x597D,0};
+ char example_7_utf7[] = "+T";
+
+ /* tests a buffer that runs out in the middle of decoding a UTF-7 sequence */
+ char example_8_utf7[] = "+T2BZfQ-";
+ WCHAR example_8_utf16[] = {0x4F60, 0x597D, 0};
+
+ char c_buffer[256] = {0};
+ WCHAR w_buffer[256] = {0};
+ int len;
+
+
+ len = WideCharToMultiByte(CP_UTF7, 0, example_0_utf16, -1, c_buffer, 256, NULL, NULL);
+ ok(len == example_0_utf7_len && strcmp(c_buffer, example_0_utf7) == 0, "len=%i dst=\"%s\"\n", len, c_buffer);
+
+ len = MultiByteToWideChar(CP_UTF7, 0, example_0_utf7, -1, w_buffer, 256);
+ ok(len == example_0_utf16_len && winetest_strcmpW(w_buffer, example_0_utf16) == 0, "len=%i dst=%s\n", len, wine_dbgstr_w(w_buffer));
+
+ /* 4 more tests to just compute the required length */
+ len = WideCharToMultiByte(CP_UTF7, 0, example_0_utf16, -1, NULL, 0, NULL, NULL);
+ ok(len == example_0_utf7_len, "len=%i\n", len);
+
+ len = WideCharToMultiByte(CP_UTF7, 0, example_0_utf16, -1, c_buffer, 0, NULL, NULL);
+ ok(len == example_0_utf7_len, "len=%i\n", len);
+
+ len = MultiByteToWideChar(CP_UTF7, 0, example_0_utf7, -1, NULL, 0);
+ ok(len == example_0_utf16_len, "len=%i\n", len);
+
+ len = MultiByteToWideChar(CP_UTF7, 0, example_0_utf7, -1, w_buffer, 0);
+ ok(len == example_0_utf16_len, "len=%i\n", len);
+
+
+ len = WideCharToMultiByte(CP_UTF7, 0, example_1_utf16, -1, c_buffer, 256, NULL, NULL);
+ ok(len == example_1_utf7_len && strcmp(c_buffer, example_1_utf7) == 0, "len=%i dst=\"%s\"\n", len, c_buffer);
+
+ len = MultiByteToWideChar(CP_UTF7, 0, example_1_utf7, -1, w_buffer, 256);
+ ok(len == example_1_utf16_len && winetest_strcmpW(w_buffer, example_1_utf16) == 0, "len=%i dst=%s\n", len, wine_dbgstr_w(w_buffer));
+
+
+ len = WideCharToMultiByte(CP_UTF7, 0, example_2_utf16, example_2_utf16_len, c_buffer, 256, NULL, NULL);
+ ok(len == example_2_utf7_len && strcmp(c_buffer, example_2_utf7) == 0, "len=%i dst=\"%s\"\n", len, c_buffer);
+
+ len = MultiByteToWideChar(CP_UTF7, 0, example_2_utf7, example_2_utf7_len, w_buffer, 256);
+ ok(len == example_2_utf16_len && winetest_strcmpW(w_buffer, example_2_utf16) == 0, "len=%i dst=%s\n", len, wine_dbgstr_w(w_buffer));
+
+
+ len = MultiByteToWideChar(CP_UTF7, 0, example_3_utf7, -1, w_buffer, 256);
+ ok(len == example_3_utf16_len && winetest_strcmpW(w_buffer, example_3_utf16) == 0, "len=%i dst=%s\n", len, wine_dbgstr_w(w_buffer));
+
+
+ len = MultiByteToWideChar(CP_UTF7, 0, example_4_utf7, -1, w_buffer, 256);
+ ok(len == example_4_utf16_len && winetest_strcmpW(w_buffer, example_4_utf16) == 0, "len=%i dst=%s\n", len, wine_dbgstr_w(w_buffer));
+
+
+ memset(c_buffer, 0, sizeof(c_buffer));
+ len = WideCharToMultiByte(CP_UTF7, 0, example_5_utf16, -1, c_buffer, 2, NULL, NULL);
+ ok(len == 0 && strcmp(c_buffer, example_5_utf7) == 0, "len=%i dst=\"%s\"\n", len, c_buffer);
+
+
+ memset(w_buffer, 0, sizeof(w_buffer));
+ len = MultiByteToWideChar(CP_UTF7, 0, example_6_utf7, -1, w_buffer, 2);
+ ok(len == 0 && winetest_strcmpW(w_buffer, example_6_utf16) == 0, "len=%i dst=%s\n", len, wine_dbgstr_w(w_buffer));
+
+
+ memset(c_buffer, 0, sizeof(c_buffer));
+ len = WideCharToMultiByte(CP_UTF7, 0, example_7_utf16, -1, c_buffer, 2, NULL, NULL);
+ ok(len == 0 && strcmp(c_buffer, example_7_utf7) == 0, "len=%i dst=\"%s\"\n", len, c_buffer);
+
+
+ memset(w_buffer, 0, sizeof(w_buffer));
+ len = MultiByteToWideChar(CP_UTF7, 0, example_8_utf7, -1, w_buffer, 2);
+ ok(len == 0 && winetest_strcmpW(w_buffer, example_8_utf16) == 0, "len=%i dst=%s\n", len, wine_dbgstr_w(w_buffer));
+}
+
static void test_undefined_byte_char(void)
{
static const struct tag_testset {
@@ -477,5 +601,7 @@ START_TEST(codepage)
test_string_conversion(NULL);
test_string_conversion(&bUsedDefaultChar);
+ test_utf7_string_conversion();
+
test_undefined_byte_char();
}
--
1.7.9.5
More information about the wine-patches
mailing list