- add stubbed support for IEnumScript interface
[wine/gsoc_dplay.git] / dlls / mlang / tests / mlang.c
blob10f422cb93b79f0e827e9e9dcd52bae5df0bf537
1 /*
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
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "mlang.h"
30 #include "wine/test.h"
31 #include "wine/debug.h"
33 #ifndef CP_UNICODE
34 #define CP_UNICODE 1200
35 #endif
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};
47 char bufA[256];
48 WCHAR bufW[256];
49 UINT lenA, lenW, expected_len;
50 HRESULT ret;
51 HMODULE hMlang;
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));
66 lenA = 0;
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));
75 lenA = -1;
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));
87 lenA = -1;
88 lenW = 5;
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));
97 lenA = -1;
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);
110 lenW = 0;
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);
128 lenW = 0;
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));
138 lenW = 0;
139 lenA = 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));
147 lenW = -1;
148 lenA = 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));
159 lenW = -1;
160 lenA = 5;
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));
169 lenW = -1;
170 lenA = 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);
183 lenA = 0;
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);
192 lenA = sizeof(bufA);
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);
201 lenA = 0;
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);
223 #ifdef DUMP_CP_INFO
224 static const char *dump_mime_flags(DWORD flags)
226 static char buf[1024];
228 buf[0] = 0;
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");
244 return buf;
246 #endif
248 static void test_EnumCodePages(IMultiLanguage2 *iML2, DWORD flags)
250 IEnumCodePage *iEnumCP = NULL;
251 MIMECPINFO *cpinfo;
252 MIMECPINFO cpinfo2;
253 HRESULT ret;
254 ULONG i, n;
255 UINT total;
257 total = 0;
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);
272 n = 65536;
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);
282 n = 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);
288 n = total * 2;
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);
295 if (!flags)
297 ok(n == total, "IEnumCodePage_Next: expected %u, got %lu", total, n);
299 flags = MIMECONTF_MIME_LATEST;
302 total = n;
304 for (i = 0; i < n; i++)
306 CPINFOEXA cpinfoex;
307 CHARSETINFO csi;
308 #ifdef DUMP_CP_INFO
309 trace("MIMECPINFO #%lu:\n"
310 "dwFlags %08lx %s\n"
311 "uiCodePage %u\n"
312 "uiFamilyCodePage %u\n"
313 "wszDescription %s\n"
314 "wszWebCharset %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);
331 #endif
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);
336 else
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);
341 else
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);
345 else
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);
370 else
371 trace("IsValidCodePage failed for cp %u\n", cpinfo[i].uiCodePage);
373 trace("---\n");
376 /* now IEnumCodePage_Next should fail, since pointer is at the end */
377 n = 1;
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);
383 n = 0;
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);
388 #if 0
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);
394 #endif
395 for (i = 0; i < total - 1; i++)
397 n = 0;
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;
419 SCRIPTINFO *sinfo;
420 SCRIPTINFO sinfo2;
421 HRESULT ret;
422 ULONG i, n;
423 UINT total;
425 total = 0;
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);
440 n = 65536;
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);
450 n = 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);
455 n = total * 2;
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);
462 if (!flags)
464 ok(n == total, "IEnumScript_Next: expected %u, got %lu", total, n);
465 flags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
468 total = n;
470 for (i = 0; i < n; i++)
472 CPINFOEXA cpinfoex;
473 #ifdef DUMP_SCRIPT_INFO
474 trace("SCRIPTINFO #%lu:\n"
475 "ScriptId %08lx\n"
476 "uiCodePage %u\n"
477 "wszDescription %s\n"
478 "wszFixedWidthFont %s\n"
479 "wszProportionalFont %s\n\n",
481 sinfo[i].ScriptId,
482 sinfo[i].uiCodePage,
483 wine_dbgstr_w(sinfo[i].wszDescription),
484 wine_dbgstr_w(sinfo[i].wszFixedWidthFont),
485 wine_dbgstr_w(sinfo[i].wszProportionalFont));
486 #endif
487 if (GetCPInfoExA(sinfo[i].uiCodePage, 0, &cpinfoex))
488 trace("CodePage %u name: %s\n", sinfo[i].uiCodePage, cpinfoex.CodePageName);
489 else
490 trace("GetCPInfoExA failed for cp %u\n", sinfo[i].uiCodePage);
492 trace("---\n");
495 /* now IEnumScript_Next should fail, since pointer is at the end */
496 n = 1;
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);
502 n = 0;
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);
507 #if 0
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);
513 #endif
514 for (i = 0; i < total - 1; i++)
516 n = 0;
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);
526 START_TEST(mlang)
528 IMultiLanguage2 *iML2 = NULL;
529 HRESULT ret;
531 CoInitialize(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);
562 CoUninitialize();