2 * Unit test suite for MLANG APIs.
4 * Copyright 2004 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/test.h"
31 #include "wine/debug.h"
34 #define CP_UNICODE 1200
37 /*#define DUMP_CP_INFO*/
38 /*#define DUMP_SCRIPT_INFO*/
40 #define TRACE_2 OutputDebugStringA
42 static void test_multibyte_to_unicode_translations(IMultiLanguage2
*iML2
)
44 /* these APIs are broken regarding constness of the input buffer */
45 char stringA
[] = "Just a test string\0"; /* double 0 for CP_UNICODE tests */
46 WCHAR stringW
[] = {'J','u','s','t',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
49 UINT lenA
, lenW
, expected_len
;
52 FARPROC pConvertINetMultiByteToUnicode
;
53 FARPROC pConvertINetUnicodeToMultiByte
;
55 hMlang
= LoadLibraryA("mlang.dll");
56 ok(hMlang
!= 0, "couldn't load mlang.dll\n");
58 pConvertINetMultiByteToUnicode
= GetProcAddress(hMlang
, "ConvertINetMultiByteToUnicode");
59 ok(pConvertINetMultiByteToUnicode
!= NULL
, "couldn't resolve ConvertINetMultiByteToUnicode\n");
60 pConvertINetUnicodeToMultiByte
= GetProcAddress(hMlang
, "ConvertINetUnicodeToMultiByte");
61 ok(pConvertINetUnicodeToMultiByte
!= NULL
, "couldn't resolve ConvertINetUnicodeToMultiByte\n");
63 /* IMultiLanguage2_ConvertStringToUnicode tests */
65 memset(bufW
, 'x', sizeof(bufW
));
67 lenW
= sizeof(bufW
)/sizeof(bufW
[0]);
68 TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n");
69 ret
= IMultiLanguage2_ConvertStringToUnicode(iML2
, NULL
, 1252, stringA
, &lenA
, bufW
, &lenW
);
70 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringToUnicode failed: %08lx\n", ret
);
71 ok(lenA
== 0, "expected lenA 0, got %u\n", lenA
);
72 ok(lenW
== 0, "expected lenW 0, got %u\n", lenW
);
74 memset(bufW
, 'x', sizeof(bufW
));
76 lenW
= sizeof(bufW
)/sizeof(bufW
[0]);
77 TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n");
78 ret
= IMultiLanguage2_ConvertStringToUnicode(iML2
, NULL
, 1252, stringA
, &lenA
, bufW
, &lenW
);
79 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringToUnicode failed: %08lx\n", ret
);
80 ok(lenA
== lstrlenA(stringA
), "expected lenA %u, got %u\n", lstrlenA(stringA
), lenA
);
81 ok(lenW
== lstrlenW(stringW
), "expected lenW %u, got %u\n", lstrlenW(stringW
), lenW
);
82 ok(bufW
[lenW
] != 0, "buf should not be 0 terminated\n");
83 bufW
[lenW
] = 0; /* -1 doesn't include 0 terminator */
84 ok(!lstrcmpW(bufW
, stringW
), "bufW/stringW mismatch\n");
86 memset(bufW
, 'x', sizeof(bufW
));
89 TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n");
90 ret
= IMultiLanguage2_ConvertStringToUnicode(iML2
, NULL
, 1252, stringA
, &lenA
, bufW
, &lenW
);
91 ok(ret
== E_FAIL
, "IMultiLanguage2_ConvertStringToUnicode should fail: %08lx\n", ret
);
92 ok(lenW
== 0, "expected lenW 0, got %u\n", lenW
);
93 /* still has to do partial conversion */
94 ok(!memcmp(bufW
, stringW
, 5 * sizeof(WCHAR
)), "bufW/stringW mismatch\n");
96 memset(bufW
, 'x', sizeof(bufW
));
98 lenW
= sizeof(bufW
)/sizeof(bufW
[0]);
99 TRACE_2("Call IMultiLanguage2_ConvertStringToUnicode\n");
100 ret
= IMultiLanguage2_ConvertStringToUnicode(iML2
, NULL
, CP_UNICODE
, stringA
, &lenA
, bufW
, &lenW
);
101 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringToUnicode failed: %08lx\n", ret
);
102 ok(lenA
== lstrlenA(stringA
), "expected lenA %u, got %u\n", lstrlenA(stringA
), lenA
);
103 ok(lenW
== lstrlenW(stringW
)/sizeof(WCHAR
), "expected lenW %u, got %u\n", lstrlenW(stringW
)/sizeof(WCHAR
), lenW
);
104 ok(bufW
[lenW
] != 0, "buf should not be 0 terminated\n");
105 bufW
[lenW
] = 0; /* -1 doesn't include 0 terminator */
106 ok(!lstrcmpA((LPCSTR
)bufW
, stringA
), "bufW/stringA mismatch\n");
108 memset(bufW
, 'x', sizeof(bufW
));
109 lenA
= lstrlenA(stringA
);
111 ret
= IMultiLanguage2_ConvertStringToUnicode(iML2
, NULL
, 1252, stringA
, &lenA
, NULL
, &lenW
);
112 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringToUnicode failed: %08lx\n", ret
);
113 ok(lenA
== lstrlenA(stringA
), "expected lenA %u, got %u\n", lstrlenA(stringA
), lenA
);
114 expected_len
= MultiByteToWideChar(1252, 0, stringA
, lenA
, NULL
, 0);
115 ok(lenW
== expected_len
, "expected lenW %u, got %u\n", expected_len
, lenW
);
117 memset(bufW
, 'x', sizeof(bufW
));
118 lenA
= lstrlenA(stringA
);
119 lenW
= sizeof(bufW
)/sizeof(bufW
[0]);
120 ret
= pConvertINetMultiByteToUnicode(NULL
, 1252, stringA
, &lenA
, NULL
, &lenW
);
121 ok(ret
== S_OK
, "ConvertINetMultiByteToUnicode failed: %08lx\n", ret
);
122 ok(lenA
== lstrlenA(stringA
), "expected lenA %u, got %u\n", lstrlenA(stringA
), lenA
);
123 expected_len
= MultiByteToWideChar(1252, 0, stringA
, lenA
, NULL
, 0);
124 ok(lenW
== expected_len
, "expected lenW %u, got %u\n", expected_len
, lenW
);
126 memset(bufW
, 'x', sizeof(bufW
));
127 lenA
= lstrlenA(stringA
);
129 ret
= pConvertINetMultiByteToUnicode(NULL
, 1252, stringA
, &lenA
, NULL
, &lenW
);
130 ok(ret
== S_OK
, "ConvertINetMultiByteToUnicode failed: %08lx\n", ret
);
131 ok(lenA
== lstrlenA(stringA
), "expected lenA %u, got %u\n", lstrlenA(stringA
), lenA
);
132 expected_len
= MultiByteToWideChar(1252, 0, stringA
, lenA
, NULL
, 0);
133 ok(lenW
== expected_len
, "expected lenW %u, got %u\n", expected_len
, lenW
);
135 /* IMultiLanguage2_ConvertStringFromUnicode tests */
137 memset(bufA
, 'x', sizeof(bufA
));
140 TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n");
141 ret
= IMultiLanguage2_ConvertStringFromUnicode(iML2
, NULL
, 1252, stringW
, &lenW
, bufA
, &lenA
);
142 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringFromUnicode failed: %08lx\n", ret
);
143 ok(lenA
== 0, "expected lenA 0, got %u\n", lenA
);
144 ok(lenW
== 0, "expected lenW 0, got %u\n", lenW
);
146 memset(bufA
, 'x', sizeof(bufA
));
149 TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n");
150 ret
= IMultiLanguage2_ConvertStringFromUnicode(iML2
, NULL
, 1252, stringW
, &lenW
, bufA
, &lenA
);
151 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringFromUnicode failed: %08lx\n", ret
);
152 ok(lenA
== lstrlenA(stringA
), "expected lenA %u, got %u\n", lstrlenA(stringA
), lenA
);
153 ok(lenW
== lstrlenW(stringW
), "expected lenW %u, got %u\n", lstrlenW(stringW
), lenW
);
154 ok(bufA
[lenA
] != 0, "buf should not be 0 terminated\n");
155 bufA
[lenA
] = 0; /* -1 doesn't include 0 terminator */
156 ok(!lstrcmpA(bufA
, stringA
), "bufA/stringA mismatch\n");
158 memset(bufA
, 'x', sizeof(bufA
));
161 TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n");
162 ret
= IMultiLanguage2_ConvertStringFromUnicode(iML2
, NULL
, 1252, stringW
, &lenW
, bufA
, &lenA
);
163 ok(ret
== E_FAIL
, "IMultiLanguage2_ConvertStringFromUnicode should fail: %08lx\n", ret
);
164 ok(lenA
== 0, "expected lenA 0, got %u\n", lenA
);
165 /* still has to do partial conversion */
166 ok(!memcmp(bufA
, stringA
, 5), "bufW/stringW mismatch\n");
168 memset(bufA
, 'x', sizeof(bufA
));
171 TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n");
172 ret
= IMultiLanguage2_ConvertStringFromUnicode(iML2
, NULL
, CP_UNICODE
, stringW
, &lenW
, bufA
, &lenA
);
173 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringFromUnicode failed: %08lx\n", ret
);
174 ok(lenA
== lstrlenA(stringA
) * sizeof(WCHAR
), "expected lenA %u, got %u\n", lstrlenA(stringA
) * sizeof(WCHAR
), lenA
);
175 ok(lenW
== lstrlenW(stringW
), "expected lenW %u, got %u\n", lstrlenW(stringW
), lenW
);
176 ok(bufA
[lenA
] != 0 && bufA
[lenA
+1] != 0, "buf should not be 0 terminated\n");
177 bufA
[lenA
] = 0; /* -1 doesn't include 0 terminator */
178 bufA
[lenA
+1] = 0; /* sizeof(WCHAR) */
179 ok(!lstrcmpW((LPCWSTR
)bufA
, stringW
), "bufA/stringW mismatch\n");
181 memset(bufA
, 'x', sizeof(bufA
));
182 lenW
= lstrlenW(stringW
);
184 ret
= IMultiLanguage2_ConvertStringFromUnicode(iML2
, NULL
, 1252, stringW
, &lenW
, NULL
, &lenA
);
185 ok(ret
== S_OK
, "IMultiLanguage2_ConvertStringFromUnicode failed: %08lx\n", ret
);
186 ok(lenW
== lstrlenW(stringW
), "expected lenW %u, got %u\n", lstrlenW(stringW
), lenW
);
187 expected_len
= WideCharToMultiByte(1252, 0, stringW
, lenW
, NULL
, 0, NULL
, NULL
);
188 ok(lenA
== expected_len
, "expected lenA %u, got %u\n", expected_len
, lenA
);
190 memset(bufA
, 'x', sizeof(bufA
));
191 lenW
= lstrlenW(stringW
);
193 ret
= pConvertINetUnicodeToMultiByte(NULL
, 1252, stringW
, &lenW
, NULL
, &lenA
);
194 ok(ret
== S_OK
, "ConvertINetUnicodeToMultiByte failed: %08lx\n", ret
);
195 ok(lenW
== lstrlenW(stringW
), "expected lenW %u, got %u\n", lstrlenW(stringW
), lenW
);
196 expected_len
= WideCharToMultiByte(1252, 0, stringW
, lenW
, NULL
, 0, NULL
, NULL
);
197 ok(lenA
== expected_len
, "expected lenA %u, got %u\n", expected_len
, lenA
);
199 memset(bufA
, 'x', sizeof(bufA
));
200 lenW
= lstrlenW(stringW
);
202 ret
= pConvertINetUnicodeToMultiByte(NULL
, 1252, stringW
, &lenW
, NULL
, &lenA
);
203 ok(ret
== S_OK
, "ConvertINetUnicodeToMultiByte failed: %08lx\n", ret
);
204 ok(lenW
== lstrlenW(stringW
), "expected lenW %u, got %u\n", lstrlenW(stringW
), lenW
);
205 expected_len
= WideCharToMultiByte(1252, 0, stringW
, lenW
, NULL
, 0, NULL
, NULL
);
206 ok(lenA
== expected_len
, "expected lenA %u, got %u\n", expected_len
, lenA
);
209 static void inline cpinfo_cmp(MIMECPINFO
*cpinfo1
, MIMECPINFO
*cpinfo2
)
211 ok(cpinfo1
->dwFlags
== cpinfo2
->dwFlags
, "dwFlags mismatch: %08lx != %08lx\n", cpinfo1
->dwFlags
, cpinfo2
->dwFlags
);
212 ok(cpinfo1
->uiCodePage
== cpinfo2
->uiCodePage
, "uiCodePage mismatch: %u != %u\n", cpinfo1
->uiCodePage
, cpinfo2
->uiCodePage
);
213 ok(cpinfo1
->uiFamilyCodePage
== cpinfo2
->uiFamilyCodePage
, "uiFamilyCodePage mismatch: %u != %u\n", cpinfo1
->uiFamilyCodePage
, cpinfo2
->uiFamilyCodePage
);
214 ok(!lstrcmpW(cpinfo1
->wszDescription
, cpinfo2
->wszDescription
), "wszDescription mismatch\n");
215 ok(!lstrcmpW(cpinfo1
->wszWebCharset
, cpinfo2
->wszWebCharset
), "wszWebCharset mismatch\n");
216 ok(!lstrcmpW(cpinfo1
->wszHeaderCharset
, cpinfo2
->wszHeaderCharset
), "wszHeaderCharset mismatch\n");
217 ok(!lstrcmpW(cpinfo1
->wszBodyCharset
, cpinfo2
->wszBodyCharset
), "wszBodyCharset mismatch\n");
218 ok(!lstrcmpW(cpinfo1
->wszFixedWidthFont
, cpinfo2
->wszFixedWidthFont
), "wszFixedWidthFont mismatch\n");
219 ok(!lstrcmpW(cpinfo1
->wszProportionalFont
, cpinfo2
->wszProportionalFont
), "wszProportionalFont mismatch\n");
220 ok(cpinfo1
->bGDICharset
== cpinfo2
->bGDICharset
, "bGDICharset mismatch: %d != %d\n", cpinfo1
->bGDICharset
, cpinfo2
->bGDICharset
);
224 static const char *dump_mime_flags(DWORD flags
)
226 static char buf
[1024];
230 if (flags
& MIMECONTF_MAILNEWS
) strcat(buf
, " MIMECONTF_MAILNEWS");
231 if (flags
& MIMECONTF_BROWSER
) strcat(buf
, " MIMECONTF_BROWSER");
232 if (flags
& MIMECONTF_MINIMAL
) strcat(buf
, " MIMECONTF_MINIMAL");
233 if (flags
& MIMECONTF_IMPORT
) strcat(buf
, " MIMECONTF_IMPORT");
234 if (flags
& MIMECONTF_SAVABLE_MAILNEWS
) strcat(buf
, " MIMECONTF_SAVABLE_MAILNEWS");
235 if (flags
& MIMECONTF_SAVABLE_BROWSER
) strcat(buf
, " MIMECONTF_SAVABLE_BROWSER");
236 if (flags
& MIMECONTF_EXPORT
) strcat(buf
, " MIMECONTF_EXPORT");
237 if (flags
& MIMECONTF_PRIVCONVERTER
) strcat(buf
, " MIMECONTF_PRIVCONVERTER");
238 if (flags
& MIMECONTF_VALID
) strcat(buf
, " MIMECONTF_VALID");
239 if (flags
& MIMECONTF_VALID_NLS
) strcat(buf
, " MIMECONTF_VALID_NLS");
240 if (flags
& MIMECONTF_MIME_IE4
) strcat(buf
, " MIMECONTF_MIME_IE4");
241 if (flags
& MIMECONTF_MIME_LATEST
) strcat(buf
, " MIMECONTF_MIME_LATEST");
242 if (flags
& MIMECONTF_MIME_REGISTRY
) strcat(buf
, " MIMECONTF_MIME_REGISTRY");
248 static void test_EnumCodePages(IMultiLanguage2
*iML2
, DWORD flags
)
250 IEnumCodePage
*iEnumCP
= NULL
;
258 TRACE_2("Call IMultiLanguage2_GetNumberOfCodePageInfo\n");
259 ret
= IMultiLanguage2_GetNumberOfCodePageInfo(iML2
, &total
);
260 ok(ret
== S_OK
&& total
!= 0, "IMultiLanguage2_GetNumberOfCodePageInfo: expected S_OK/!0, got %08lx/%u\n", ret
, total
);
262 trace("total mlang supported codepages %u\n", total
);
264 TRACE_2("Call IMultiLanguage2_EnumCodePages\n");
265 ret
= IMultiLanguage2_EnumCodePages(iML2
, flags
, LANG_NEUTRAL
, &iEnumCP
);
266 trace("IMultiLanguage2_EnumCodePages = %08lx, iEnumCP = %p\n", ret
, iEnumCP
);
267 ok(ret
== S_OK
&& iEnumCP
, "IMultiLanguage2_EnumCodePages: expected S_OK/!NULL, got %08lx/%p\n", ret
, iEnumCP
);
269 TRACE_2("Call IEnumCodePage_Reset\n");
270 ret
= IEnumCodePage_Reset(iEnumCP
);
271 ok(ret
== S_OK
, "IEnumCodePage_Reset: expected S_OK, got %08lx\n", ret
);
273 TRACE_2("Call IEnumCodePage_Next\n");
274 ret
= IEnumCodePage_Next(iEnumCP
, 0, NULL
, &n
);
275 ok(n
== 0 && ret
== S_FALSE
, "IEnumCodePage_Next: expected 0/S_FALSE, got %lu/%08lx\n", n
, ret
);
276 TRACE_2("Call IEnumCodePage_Next\n");
277 ret
= IEnumCodePage_Next(iEnumCP
, 0, NULL
, NULL
);
278 ok(ret
== S_FALSE
, "IEnumCodePage_Next: expected S_FALSE, got %08lx\n", ret
);
280 cpinfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cpinfo
) * total
* 2);
283 TRACE_2("Call IEnumCodePage_Next\n");
284 ret
= IEnumCodePage_Next(iEnumCP
, 0, cpinfo
, &n
);
285 trace("IEnumCodePage_Next = %08lx, n = %lu\n", ret
, n
);
286 ok(ret
== S_FALSE
&& n
== 0, "IEnumCodePage_Next: expected S_FALSE/0, got %08lx/%lu\n", ret
, n
);
289 TRACE_2("Call IEnumCodePage_Next\n");
290 ret
= IEnumCodePage_Next(iEnumCP
, n
, cpinfo
, &n
);
291 ok(ret
== S_OK
&& n
!= 0, "IEnumCodePage_Next: expected S_OK/!0, got %08lx/%lu\n", ret
, n
);
293 trace("flags %08lx, enumerated codepages %lu\n", flags
, n
);
297 ok(n
== total
, "IEnumCodePage_Next: expected %u, got %lu", total
, n
);
299 flags
= MIMECONTF_MIME_LATEST
;
304 for (i
= 0; i
< n
; i
++)
309 trace("MIMECPINFO #%lu:\n"
312 "uiFamilyCodePage %u\n"
313 "wszDescription %s\n"
315 "wszHeaderCharset %s\n"
316 "wszBodyCharset %s\n"
317 "wszFixedWidthFont %s\n"
318 "wszProportionalFont %s\n"
319 "bGDICharset %d\n\n",
321 cpinfo
[i
].dwFlags
, dump_mime_flags(cpinfo
[i
].dwFlags
),
322 cpinfo
[i
].uiCodePage
,
323 cpinfo
[i
].uiFamilyCodePage
,
324 wine_dbgstr_w(cpinfo
[i
].wszDescription
),
325 wine_dbgstr_w(cpinfo
[i
].wszWebCharset
),
326 wine_dbgstr_w(cpinfo
[i
].wszHeaderCharset
),
327 wine_dbgstr_w(cpinfo
[i
].wszBodyCharset
),
328 wine_dbgstr_w(cpinfo
[i
].wszFixedWidthFont
),
329 wine_dbgstr_w(cpinfo
[i
].wszProportionalFont
),
330 cpinfo
[i
].bGDICharset
);
332 ok(cpinfo
[i
].dwFlags
& flags
, "enumerated flags %08lx do not include requested %08lx\n", cpinfo
[i
].dwFlags
, flags
);
334 if (TranslateCharsetInfo((DWORD
*)cpinfo
[i
].uiFamilyCodePage
, &csi
, TCI_SRCCODEPAGE
))
335 ok(cpinfo
[i
].bGDICharset
== csi
.ciCharset
, "%d != %d\n", cpinfo
[i
].bGDICharset
, csi
.ciCharset
);
337 trace("TranslateCharsetInfo failed for cp %u\n", cpinfo
[i
].uiFamilyCodePage
);
339 if (GetCPInfoExA(cpinfo
[i
].uiCodePage
, 0, &cpinfoex
))
340 trace("CodePage %u name: %s\n", cpinfo
[i
].uiCodePage
, cpinfoex
.CodePageName
);
342 trace("GetCPInfoExA failed for cp %u\n", cpinfo
[i
].uiCodePage
);
343 if (GetCPInfoExA(cpinfo
[i
].uiFamilyCodePage
, 0, &cpinfoex
))
344 trace("CodePage %u name: %s\n", cpinfo
[i
].uiFamilyCodePage
, cpinfoex
.CodePageName
);
346 trace("GetCPInfoExA failed for cp %u\n", cpinfo
[i
].uiFamilyCodePage
);
348 /* Win95 does not support UTF-7 */
349 if (cpinfo
[i
].uiCodePage
== CP_UTF7
) continue;
351 /* support files for some codepages might be not installed, or
352 * the codepage is just an alias.
354 if (IsValidCodePage(cpinfo
[i
].uiCodePage
))
356 TRACE_2("Call IMultiLanguage2_IsConvertible\n");
357 ret
= IMultiLanguage2_IsConvertible(iML2
, cpinfo
[i
].uiCodePage
, CP_UNICODE
);
358 ok(ret
== S_OK
, "IMultiLanguage2_IsConvertible(%u -> CP_UNICODE) = %08lx\n", cpinfo
[i
].uiCodePage
, ret
);
359 TRACE_2("Call IMultiLanguage2_IsConvertible\n");
360 ret
= IMultiLanguage2_IsConvertible(iML2
, CP_UNICODE
, cpinfo
[i
].uiCodePage
);
361 ok(ret
== S_OK
, "IMultiLanguage2_IsConvertible(CP_UNICODE -> %u) = %08lx\n", cpinfo
[i
].uiCodePage
, ret
);
363 TRACE_2("Call IMultiLanguage2_IsConvertible\n");
364 ret
= IMultiLanguage2_IsConvertible(iML2
, cpinfo
[i
].uiCodePage
, CP_UTF8
);
365 ok(ret
== S_OK
, "IMultiLanguage2_IsConvertible(%u -> CP_UTF8) = %08lx\n", cpinfo
[i
].uiCodePage
, ret
);
366 TRACE_2("Call IMultiLanguage2_IsConvertible\n");
367 ret
= IMultiLanguage2_IsConvertible(iML2
, CP_UTF8
, cpinfo
[i
].uiCodePage
);
368 ok(ret
== S_OK
, "IMultiLanguage2_IsConvertible(CP_UTF8 -> %u) = %08lx\n", cpinfo
[i
].uiCodePage
, ret
);
371 trace("IsValidCodePage failed for cp %u\n", cpinfo
[i
].uiCodePage
);
376 /* now IEnumCodePage_Next should fail, since pointer is at the end */
378 ret
= IEnumCodePage_Next(iEnumCP
, 1, &cpinfo2
, &n
);
379 ok(ret
== S_FALSE
&& n
== 0, "IEnumCodePage_Next: expected S_FALSE/0, got %08lx/%lu\n", ret
, n
);
381 ret
= IEnumCodePage_Reset(iEnumCP
);
382 ok(ret
== S_OK
, "IEnumCodePage_Reset: expected S_OK, got %08lx\n", ret
);
384 ret
= IEnumCodePage_Next(iEnumCP
, 1, &cpinfo2
, &n
);
385 ok(n
== 1 && ret
== S_OK
, "IEnumCodePage_Next: expected 1/S_OK, got %lu/%08lx\n", n
, ret
);
386 cpinfo_cmp(&cpinfo
[0], &cpinfo2
);
389 /* Due to a bug in MS' implementation of IEnumCodePage_Skip
390 * it's not used here.
392 ret
= IEnumCodePage_Skip(iEnumCP
, 1);
393 ok(ret
== S_OK
, "IEnumCodePage_Skip: expected S_OK, got %08lx\n", ret
);
395 for (i
= 0; i
< total
- 1; i
++)
398 ret
= IEnumCodePage_Next(iEnumCP
, 1, &cpinfo2
, &n
);
399 ok(n
== 1 && ret
== S_OK
, "IEnumCodePage_Next: expected 1/S_OK, got %lu/%08lx\n", n
, ret
);
400 cpinfo_cmp(&cpinfo
[i
+ 1], &cpinfo2
);
403 HeapFree(GetProcessHeap(), 0, cpinfo
);
404 IEnumCodePage_Release(iEnumCP
);
407 static void inline scriptinfo_cmp(SCRIPTINFO
*sinfo1
, SCRIPTINFO
*sinfo2
)
409 ok(sinfo1
->ScriptId
== sinfo2
->ScriptId
, "ScriptId mismatch: %d != %d\n", sinfo1
->ScriptId
, sinfo2
->ScriptId
);
410 ok(sinfo1
->uiCodePage
== sinfo2
->uiCodePage
, "uiCodePage mismatch: %u != %u\n", sinfo1
->uiCodePage
, sinfo2
->uiCodePage
);
411 ok(!lstrcmpW(sinfo1
->wszDescription
, sinfo2
->wszDescription
), "wszDescription mismatch\n");
412 ok(!lstrcmpW(sinfo1
->wszFixedWidthFont
, sinfo2
->wszFixedWidthFont
), "wszFixedWidthFont mismatch\n");
413 ok(!lstrcmpW(sinfo1
->wszProportionalFont
, sinfo2
->wszProportionalFont
), "wszProportionalFont mismatch\n");
416 static void test_EnumScripts(IMultiLanguage2
*iML2
, DWORD flags
)
418 IEnumScript
*iEnumScript
= NULL
;
426 TRACE_2("Call IMultiLanguage2_GetNumberOfScripts\n");
427 ret
= IMultiLanguage2_GetNumberOfScripts(iML2
, &total
);
428 ok(ret
== S_OK
&& total
!= 0, "IMultiLanguage2_GetNumberOfScripts: expected S_OK/!0, got %08lx/%u\n", ret
, total
);
430 trace("total mlang supported scripts %u\n", total
);
432 TRACE_2("Call IMultiLanguage2_EnumScripts\n");
433 ret
= IMultiLanguage2_EnumScripts(iML2
, flags
, LANG_NEUTRAL
, &iEnumScript
);
434 trace("IMultiLanguage2_EnumScripts = %08lx, iEnumScript = %p\n", ret
, iEnumScript
);
435 ok(ret
== S_OK
&& iEnumScript
, "IMultiLanguage2_EnumScripts: expected S_OK/!NULL, got %08lx/%p\n", ret
, iEnumScript
);
437 TRACE_2("Call IEnumScript_Reset\n");
438 ret
= IEnumScript_Reset(iEnumScript
);
439 ok(ret
== S_OK
, "IEnumScript_Reset: expected S_OK, got %08lx\n", ret
);
441 TRACE_2("Call IEnumScript_Next\n");
442 ret
= IEnumScript_Next(iEnumScript
, 0, NULL
, &n
);
443 ok(n
== 65536 && ret
== E_FAIL
, "IEnumScript_Next: expected 65536/E_FAIL, got %lu/%08lx\n", n
, ret
);
444 TRACE_2("Call IEnumScript_Next\n");
445 ret
= IEnumScript_Next(iEnumScript
, 0, NULL
, NULL
);
446 ok(ret
== E_FAIL
, "IEnumScript_Next: expected E_FAIL, got %08lx\n", ret
);
448 sinfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*sinfo
) * total
* 2);
451 TRACE_2("Call IEnumScript_Next\n");
452 ret
= IEnumScript_Next(iEnumScript
, 0, sinfo
, &n
);
453 ok(ret
== S_FALSE
&& n
== 0, "IEnumScript_Next: expected S_FALSE/0, got %08lx/%lu\n", ret
, n
);
456 TRACE_2("Call IEnumScript_Next\n");
457 ret
= IEnumScript_Next(iEnumScript
, n
, sinfo
, &n
);
458 ok(ret
== S_OK
&& n
!= 0, "IEnumScript_Next: expected S_OK, got %08lx/%lu\n", ret
, n
);
460 trace("flags %08lx, enumerated scripts %lu\n", flags
, n
);
464 ok(n
== total
, "IEnumScript_Next: expected %u, got %lu", total
, n
);
465 flags
= SCRIPTCONTF_SCRIPT_USER
| SCRIPTCONTF_SCRIPT_HIDE
| SCRIPTCONTF_SCRIPT_SYSTEM
;
470 for (i
= 0; i
< n
; i
++)
473 #ifdef DUMP_SCRIPT_INFO
474 trace("SCRIPTINFO #%lu:\n"
477 "wszDescription %s\n"
478 "wszFixedWidthFont %s\n"
479 "wszProportionalFont %s\n\n",
483 wine_dbgstr_w(sinfo
[i
].wszDescription
),
484 wine_dbgstr_w(sinfo
[i
].wszFixedWidthFont
),
485 wine_dbgstr_w(sinfo
[i
].wszProportionalFont
));
487 if (GetCPInfoExA(sinfo
[i
].uiCodePage
, 0, &cpinfoex
))
488 trace("CodePage %u name: %s\n", sinfo
[i
].uiCodePage
, cpinfoex
.CodePageName
);
490 trace("GetCPInfoExA failed for cp %u\n", sinfo
[i
].uiCodePage
);
495 /* now IEnumScript_Next should fail, since pointer is at the end */
497 ret
= IEnumScript_Next(iEnumScript
, 1, &sinfo2
, &n
);
498 ok(ret
== S_FALSE
&& n
== 0, "IEnumScript_Next: expected S_FALSE/0, got %08lx/%lu\n", ret
, n
);
500 ret
= IEnumScript_Reset(iEnumScript
);
501 ok(ret
== S_OK
, "IEnumScript_Reset: expected S_OK, got %08lx\n", ret
);
503 ret
= IEnumScript_Next(iEnumScript
, 1, &sinfo2
, &n
);
504 ok(n
== 1 && ret
== S_OK
, "IEnumScript_Next: expected 1/S_OK, got %lu/%08lx\n", n
, ret
);
505 scriptinfo_cmp(&sinfo
[0], &sinfo2
);
508 /* Due to a bug in MS' implementation of IEnumScript_Skip
509 * it's not used here.
511 ret
= IEnumScript_Skip(iEnumScript
, 1);
512 ok(ret
== S_OK
, "IEnumScript_Skip: expected S_OK, got %08lx\n", ret
);
514 for (i
= 0; i
< total
- 1; i
++)
517 ret
= IEnumScript_Next(iEnumScript
, 1, &sinfo2
, &n
);
518 ok(n
== 1 && ret
== S_OK
, "IEnumScript_Next: expected 1/S_OK, got %lu/%08lx\n", n
, ret
);
519 scriptinfo_cmp(&sinfo
[i
+ 1], &sinfo2
);
522 HeapFree(GetProcessHeap(), 0, sinfo
);
523 IEnumScript_Release(iEnumScript
);
528 IMultiLanguage2
*iML2
= NULL
;
532 TRACE_2("Call CoCreateInstance\n");
533 ret
= CoCreateInstance(&CLSID_CMultiLanguage
, NULL
, CLSCTX_INPROC_SERVER
,
534 &IID_IMultiLanguage2
, (void **)&iML2
);
536 trace("ret = %08lx, MultiLanguage2 iML2 = %p\n", ret
, iML2
);
537 if (ret
!= S_OK
|| !iML2
) return;
539 test_EnumCodePages(iML2
, 0);
540 test_EnumCodePages(iML2
, MIMECONTF_MIME_LATEST
);
541 test_EnumCodePages(iML2
, MIMECONTF_BROWSER
);
542 test_EnumCodePages(iML2
, MIMECONTF_MINIMAL
);
543 test_EnumCodePages(iML2
, MIMECONTF_VALID
);
544 /* FIXME: why MIMECONTF_MIME_REGISTRY returns 0 of supported codepages? */
545 /*test_EnumCodePages(iML2, MIMECONTF_MIME_REGISTRY);*/
547 test_EnumScripts(iML2
, 0);
548 test_EnumScripts(iML2
, SCRIPTCONTF_SCRIPT_USER
);
549 test_EnumScripts(iML2
, SCRIPTCONTF_SCRIPT_USER
| SCRIPTCONTF_SCRIPT_HIDE
| SCRIPTCONTF_SCRIPT_SYSTEM
);
551 TRACE_2("Call IMultiLanguage2_IsConvertible\n");
552 ret
= IMultiLanguage2_IsConvertible(iML2
, CP_UTF8
, CP_UNICODE
);
553 ok(ret
== S_OK
, "IMultiLanguage2_IsConvertible(CP_UTF8 -> CP_UNICODE) = %08lx\n", ret
);
554 TRACE_2("Call IMultiLanguage2_IsConvertible\n");
555 ret
= IMultiLanguage2_IsConvertible(iML2
, CP_UNICODE
, CP_UTF8
);
556 ok(ret
== S_OK
, "IMultiLanguage2_IsConvertible(CP_UNICODE -> CP_UTF8) = %08lx\n", ret
);
558 test_multibyte_to_unicode_translations(iML2
);
560 IMultiLanguage2_Release(iML2
);