ReactOS 0.4.15-dev-8116-gf69e256
mlang.c
Go to the documentation of this file.
1/*
2 * Unit test suite for MLANG APIs.
3 *
4 * Copyright 2004 Dmitry Timoshkov
5 * Copyright 2009 Detlef Riekenberg
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#define COBJMACROS
23#ifdef __REACTOS__
24#define CONST_VTABLE
25#endif
26
27#include <stdarg.h>
28#include <stdio.h>
29
30#include "windef.h"
31#include "winbase.h"
32#include "winerror.h"
33#include "initguid.h"
34#include "mlang.h"
35
36#include "wine/test.h"
37
38#ifndef CP_UNICODE
39#define CP_UNICODE 1200
40#endif
41
42/* #define DUMP_CP_INFO */
43/* #define DUMP_SCRIPT_INFO */
44
45static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
46static HRESULT (WINAPI *pConvertINetMultiByteToUnicode)(LPDWORD, DWORD, LPCSTR,
48static HRESULT (WINAPI *pConvertINetUnicodeToMultiByte)(LPDWORD, DWORD, LPCWSTR,
50static HRESULT (WINAPI *pRfc1766ToLcidA)(LCID *, LPCSTR);
51static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
52
53typedef struct lcid_tag_table {
60
61/* en, ar and zh use SUBLANG_NEUTRAL for the rfc1766 name without the country
62 all others suppress the country with SUBLANG_DEFAULT.
63 For 3 letter language codes, the rfc1766 is too small for the country */
64
65static const lcid_table_entry lcid_table[] = {
66 {"e", -1, E_FAIL},
67 {"", -1, E_FAIL},
68 {"-", -1, E_FAIL},
69 {"e-", -1, E_FAIL},
70
71 {"ar", 1, S_OK},
72 {"zh", 4, S_OK},
73
74 {"de", 0x0407, S_OK},
75 {"de-ch", 0x0807, S_OK},
76 {"de-at", 0x0c07, S_OK},
77 {"de-lu", 0x1007, S_OK},
78 {"de-li", 0x1407, S_OK},
79
80 {"en", 9, S_OK},
81 {"en-gb", 0x809, S_OK},
82 {"en-GB", 0x809, S_OK},
83 {"EN-GB", 0x809, S_OK},
84 {"en-US", 0x409, S_OK},
85 {"en-us", 0x409, S_OK},
86
87 {"fr", 0x040c, S_OK},
88 {"fr-be", 0x080c, S_OK},
89 {"fr-ca", 0x0c0c, S_OK},
90 {"fr-ch", 0x100c, S_OK},
91 {"fr-lu", 0x140c, S_OK},
92 {"fr-mc", 0x180c, S_OK, 0x040c, "fr"},
93
94 {"it", 0x0410, S_OK},
95 {"it-ch", 0x0810, S_OK},
96
97 {"nl", 0x0413, S_OK},
98 {"nl-be", 0x0813, S_OK},
99 {"pl", 0x0415, S_OK},
100 {"ru", 0x0419, S_OK},
101
102 {"kok", 0x0457, S_OK, 0x0412, "x-kok"}
103
104};
105
106#define TODO_NAME 1
107
108typedef struct info_table_tag {
116
117static const WCHAR de_en[] = {'E','n','g','l','i','s','c','h',0};
118static const WCHAR de_enca[] = {'E','n','g','l','i','s','c','h',' ',
119 '(','K','a','n','a','d','a',')',0};
120static const WCHAR de_engb[] = {'E','n','g','l','i','s','c','h',' ',
121 '(','G','r','o',0xDF,'b','r','i','t','a','n','n','i','e','n',')',0};
122static const WCHAR de_engb2[] ={'E','n','g','l','i','s','c','h',' ',
123 '(','V','e','r','e','i','n','i','g','t','e','s',' ',
124 'K',0xF6,'n','i','g','r','e','i','c',0};
125static const WCHAR de_enus[] = {'E','n','g','l','i','s','c','h',' ',
126 '(','U','S','A',')',0};
127static const WCHAR de_enus2[] ={'E','n','g','l','i','s','c','h',' ',
128 '(','V','e','r','e','i','n','i','g','t','e',' ',
129 'S','t','a','a','t','e','n',')',0};
130static const WCHAR de_de[] = {'D','e','u','t','s','c','h',' ',
131 '(','D','e','u','t','s','c','h','l','a','n','d',')',0};
132static const WCHAR de_deat[] = {'D','e','u','t','s','c','h',' ',
133 '(',0xD6,'s','t','e','r','r','e','i','c','h',')',0};
134static const WCHAR de_dech[] = {'D','e','u','t','s','c','h',' ',
135 '(','S','c','h','w','e','i','z',')',0};
136
137static const WCHAR en_en[] = {'E','n','g','l','i','s','h',0};
138static const WCHAR en_enca[] = {'E','n','g','l','i','s','h',' ',
139 '(','C','a','n','a','d','a',')',0};
140static const WCHAR en_engb[] = {'E','n','g','l','i','s','h',' ',
141 '(','U','n','i','t','e','d',' ','K','i','n','g','d','o','m',')',0};
142static const WCHAR en_enus[] = {'E','n','g','l','i','s','h',' ',
143 '(','U','n','i','t','e','d',' ','S','t','a','t','e','s',')',0};
144static const WCHAR en_de[] = {'G','e','r','m','a','n',' ',
145 '(','G','e','r','m','a','n','y',')',0};
146static const WCHAR en_deat[] = {'G','e','r','m','a','n',' ',
147 '(','A','u','s','t','r','i','a',')',0};
148static const WCHAR en_dech[] = {'G','e','r','m','a','n',' ',
149 '(','S','w','i','t','z','e','r','l','a','n','d',')',0};
150
151static const WCHAR fr_en[] = {'A','n','g','l','a','i','s',0};
152static const WCHAR fr_enca[] = {'A','n','g','l','a','i','s',' ',
153 '(','C','a','n','a','d','a',')',0};
154static const WCHAR fr_engb[] = {'A','n','g','l','a','i','s',' ',
155 '(','R','o','y','a','u','m','e','-','U','n','i',')',0};
156static const WCHAR fr_enus[] = {'A','n','g','l','a','i','s',' ',
157 '(',0xC9, 't','a','t','s','-','U','n','i','s',')',0};
158static const WCHAR fr_enus2[] ={'A','n','g','l','a','i','s',' ',
159 '(','U','.','S','.',')',0};
160static const WCHAR fr_de[] = {'A','l','l','e','m','a','n','d',' ',
161 '(','A','l','l','e','m','a','g','n','e',')',0};
162static const WCHAR fr_de2[] = {'A','l','l','e','m','a','n','d',' ',
163 '(','S','t','a','n','d','a','r','d',')',0};
164static const WCHAR fr_deat[] = {'A','l','l','e','m','a','n','d',' ',
165 '(','A','u','t','r','i','c','h','e',')',0};
166static const WCHAR fr_dech[] = {'A','l','l','e','m','a','n','d',' ',
167 '(','S','u','i','s','s','e',')',0};
168
169static const info_table_entry info_table[] = {
171 0, "en", en_en},
173 0, "en-us", en_enus},
175 0, "en-gb", en_engb},
177 0, "en-us", en_enus},
179 0, "en-ca", en_enca},
180
182 0, "de", en_de},
184 0, "de", en_de},
186 0, "de-ch", en_dech},
188 0, "de-at", en_deat},
189
191 TODO_NAME, "en", de_en},
193 TODO_NAME, "en-us", de_enus, de_enus2},
195 TODO_NAME, "en-gb", de_engb, de_engb2},
197 TODO_NAME, "en-us", de_enus, de_enus2},
199 TODO_NAME, "en-ca", de_enca},
200
202 TODO_NAME, "de", de_de},
204 TODO_NAME, "de",de_de},
206 TODO_NAME, "de-ch", de_dech},
208 TODO_NAME, "de-at", de_deat},
209
211 TODO_NAME, "en", fr_en},
213 TODO_NAME, "en-us", fr_enus, fr_enus2},
215 TODO_NAME, "en-gb", fr_engb},
217 TODO_NAME, "en-us", fr_enus, fr_enus2},
219 TODO_NAME, "en-ca", fr_enca},
220
222 TODO_NAME, "de", fr_de, fr_de2},
224 TODO_NAME, "de", fr_de, fr_de2},
226 TODO_NAME, "de-ch", fr_dech},
228 TODO_NAME, "de-at", fr_deat}
229
230};
231
233{
234 MIMECPINFO cpinfo;
235
245};
246
247static const struct cpinfo_test_data iml2_cpinfo_data[] =
248{
249 /* 0. Chinese Simplified (Auto-Select) */
250 {
251 {
252 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
253 50936, 936, {'C','h','i','n','e','s','e',' ','S','i','m','p','l','i','f','i','e','d',' ','(','A','u','t','o','-','S','e','l','e','c','t',')',0},
254 {'_','a','u','t','o','d','e','t','e','c','t','_','c','h','s',0},
255 {'_','a','u','t','o','d','e','t','e','c','t','_','c','h','s',0},
256 {'_','a','u','t','o','d','e','t','e','c','t','_','c','h','s',0},
257 {'S','i','m','s','u','n',0},
258 {'S','i','m','s','u','n',0}, 134
259 },
260 },
261 /* 1. Chinese Simplified (GB2312) */
262 {
263 {
264 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
265 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
266 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
267 936, 936, {'C','h','i','n','e','s','e',' ','S','i','m','p','l','i','f','i','e','d',' ','(','G','B','2','3','1','2',')',0},
268 {'g','b','2','3','1','2',0},
269 {'g','b','2','3','1','2',0},
270 {'g','b','2','3','1','2',0},
271 {'S','i','m','s','u','n',0},
272 {'S','i','m','s','u','n',0}, 134
273 },
274 },
275 /* 2. Chinese Simplified (GB2312-80) */
276 {
277 {
278 MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
279 MIMECONTF_MIME_LATEST,
280 20936, 936, {'C','h','i','n','e','s','e',' ','S','i','m','p','l','i','f','i','e','d',' ','(','G','B','2','3','1','2','-','8','0',')',0},
281 {'x','-','c','p','2','0','9','3','6',0},
282 {'x','-','c','p','2','0','9','3','6',0},
283 {'x','-','c','p','2','0','9','3','6',0},
284 {'S','i','m','s','u','n',0},
285 {'S','i','m','s','u','n',0}, 134
286 },
287 },
288 /* 3. Chinese Simplified (HZ) */
289 {
290 {
291 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
292 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
293 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
294 52936, 936, {'C','h','i','n','e','s','e',' ','S','i','m','p','l','i','f','i','e','d',' ','(','H','Z',')',0},
295 {'h','z','-','g','b','-','2','3','1','2',0},
296 {'h','z','-','g','b','-','2','3','1','2',0},
297 {'h','z','-','g','b','-','2','3','1','2',0},
298 {'S','i','m','s','u','n',0},
299 {'S','i','m','s','u','n',0}, 134
300 },
301 },
302 /* 4. Chinese Simplified (GB18030) */
303 {
304 {
305 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
306 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
307 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
308 54936, 936, {'C','h','i','n','e','s','e',' ','S','i','m','p','l','i','f','i','e','d',' ','(','G','B','1','8','0','3','0',')',0},
309 {'G','B','1','8','0','3','0',0},
310 {'G','B','1','8','0','3','0',0},
311 {'G','B','1','8','0','3','0',0},
312 {'S','i','m','s','u','n',0},
313 {'S','i','m','s','u','n',0}, 134
314 },
315 },
316 /* 5. Chinese Traditional (Auto-Select) */
317 {
318 {
319 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
320 50950, 950, {'C','h','i','n','e','s','e',' ','T','r','a','d','i','t','i','o','n','a','l',' ','(','A','u','t','o','-','S','e','l','e','c','t',')',0},
321 {'_','a','u','t','o','d','e','t','e','c','t','_','c','h','t',0},
322 {'_','a','u','t','o','d','e','t','e','c','t','_','c','h','t',0},
323 {'_','a','u','t','o','d','e','t','e','c','t','_','c','h','t',0},
324 {'M','i','n','g','L','i','u',0},
325 {'N','e','w',' ','M','i','n','g','L','i','u',0}, 136
326 },
327 },
328 /* 6. Chinese Traditional (Big5) */
329 {
330 {
331 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
332 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
333 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
334 950, 950, {'C','h','i','n','e','s','e',' ','T','r','a','d','i','t','i','o','n','a','l',' ','(','B','i','g','5',')',0},
335 {'b','i','g','5',0},
336 {'b','i','g','5',0},
337 {'b','i','g','5',0},
338 {'M','i','n','g','L','i','u',0},
339 {'N','e','w',' ','M','i','n','g','L','i','u',0}, 136
340 },
341 },
342 /* 7. Chinese Traditional (CNS) */
343 {
344 {
345 MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
346 MIMECONTF_MIME_LATEST,
347 20000, 950, {'C','h','i','n','e','s','e',' ','T','r','a','d','i','t','i','o','n','a','l',' ','(','C','N','S',')',0},
348 {'x','-','C','h','i','n','e','s','e','-','C','N','S',0},
349 {'x','-','C','h','i','n','e','s','e','-','C','N','S',0},
350 {'x','-','C','h','i','n','e','s','e','-','C','N','S',0},
351 {'M','i','n','g','L','i','u',0},
352 {'N','e','w',' ','M','i','n','g','L','i','u',0}, 136
353 },
354 },
355 /* 8. Arabic (Windows) */
356 {
357 {
358 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
359 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
360 MIMECONTF_MIME_LATEST,
361 1256, 1256, {'A','r','a','b','i','c',' ','(','W','i','n','d','o','w','s',')',0},
362 {'w','i','n','d','o','w','s','-','1','2','5','6',0},
363 {'w','i','n','d','o','w','s','-','1','2','5','6',0},
364 {'w','i','n','d','o','w','s','-','1','2','5','6',0},
365 {'S','i','m','p','l','i','f','i','e','d',' ','A','r','a','b','i','c',' ','F','i','x','e','d',0},
366 {'S','i','m','p','l','i','f','i','e','d',' ','A','r','a','b','i','c',0}, 178
367 },
368 },
369 /* 9. Baltic (Windows) */
370 {
371 {
372 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
373 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
374 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
375 1257, 1257, {'B','a','l','t','i','c',' ','(','W','i','n','d','o','w','s',')',0},
376 {'w','i','n','d','o','w','s','-','1','2','5','7',0},
377 {'w','i','n','d','o','w','s','-','1','2','5','7',0},
378 {'w','i','n','d','o','w','s','-','1','2','5','7',0},
379 {'C','o','u','r','i','e','r',' ','N','e','w',0},
380 {'A','r','i','a','l',0}, 186
381 },
382 },
383 /* 10. Central European (Windows) */
384 {
385 {
386 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
387 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
388 MIMECONTF_MIME_LATEST,
389 1250, 1250, {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e','a','n',' ','(','W','i','n','d','o','w','s',')',0},
390 {'w','i','n','d','o','w','s','-','1','2','5','0',0},
391 {'w','i','n','d','o','w','s','-','1','2','5','0',0},
392 {'i','s','o','-','8','8','5','9','-','2',0},
393 {'C','o','u','r','i','e','r',' ','N','e','w',0},
394 {'A','r','i','a','l',0}, 238
395 },
397 },
398 /* 11. Cyrillic (Windows) */
399 {
400 {
401 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
402 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
403 MIMECONTF_MIME_LATEST,
404 1251, 1251, {'C','y','r','i','l','l','i','c',' ','(','W','i','n','d','o','w','s',')',0},
405 {'w','i','n','d','o','w','s','-','1','2','5','1',0},
406 {'w','i','n','d','o','w','s','-','1','2','5','1',0},
407 {'k','o','i','8','-','r',0},
408 {'C','o','u','r','i','e','r',' ','N','e','w',0},
409 {'A','r','i','a','l',0}, 204
410 },
412 },
413 /* 12. Greek (Windows) */
414 {
415 {
416 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
417 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
418 MIMECONTF_MIME_LATEST,
419 1253, 1253, {'G','r','e','e','k',' ','(','W','i','n','d','o','w','s',')',0},
420 {'w','i','n','d','o','w','s','-','1','2','5','3',0},
421 {'w','i','n','d','o','w','s','-','1','2','5','3',0},
422 {'i','s','o','-','8','8','5','9','-','7',0},
423 {'C','o','u','r','i','e','r',' ','N','e','w',0},
424 {'A','r','i','a','l',0}, 161
425 },
427 },
428 /* 13. Hebrew (Windows) */
429 {
430 {
431 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
432 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
433 MIMECONTF_MIME_LATEST,
434 1255, 1255, {'H','e','b','r','e','w',' ','(','W','i','n','d','o','w','s',')',0},
435 {'w','i','n','d','o','w','s','-','1','2','5','5',0},
436 {'w','i','n','d','o','w','s','-','1','2','5','5',0},
437 {'w','i','n','d','o','w','s','-','1','2','5','5',0},
438 {'M','i','r','i','a','m',' ','F','i','x','e','d',0},
439 {'D','a','v','i','d',0}, 177
440 },
441 },
442 /* 14. Japanese (Shift-JIS) */
443 {
444 {
445 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
446 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
447 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
448 932, 932, {'J','a','p','a','n','e','s','e',' ','(','S','h','i','f','t','-','J','I','S',')',0},
449 {'s','h','i','f','t','_','j','i','s',0},
450 {'i','s','o','-','2','0','2','2','-','j','p',0},
451 {'i','s','o','-','2','0','2','2','-','j','p',0},
452 {'M','S',' ','G','o','t','h','i','c',0},
453 {'M','S',' ','P','G','o','t','h','i','c',0}, 128
454 }
455 },
456 /* 15. Korean */
457 {
458 {
459 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
460 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
461 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
462 949, 949, {'K','o','r','e','a','n',0},
463 {'k','s','_','c','_','5','6','0','1','-','1','9','8','7',0},
464 {'k','s','_','c','_','5','6','0','1','-','1','9','8','7',0},
465 {'k','s','_','c','_','5','6','0','1','-','1','9','8','7',0},
466 {'G','u','l','i','m','C','h','e',0},
467 {'G','u','l','i','m',0}, 129
468 },
469 },
470 /* 16. Thai (Windows) */
471 {
472 {
473 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
474 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
475 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
476 874, 874, {'T','h','a','i',' ','(','W','i','n','d','o','w','s',')',0},
477 {'w','i','n','d','o','w','s','-','8','7','4',0},
478 {'w','i','n','d','o','w','s','-','8','7','4',0},
479 {'w','i','n','d','o','w','s','-','8','7','4',0},
480 {'T','a','h','o','m','a',0},
481 {'T','a','h','o','m','a',0}, 222
482 },
484 },
485 /* 17. Turkish (Windows) */
486 {
487 {
488 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
489 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
490 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
491 1254, 1254, {'T','u','r','k','i','s','h',' ','(','W','i','n','d','o','w','s',')',0},
492 {'w','i','n','d','o','w','s','-','1','2','5','4',0},
493 {'w','i','n','d','o','w','s','-','1','2','5','4',0},
494 {'i','s','o','-','8','8','5','9','-','9',0},
495 {'C','o','u','r','i','e','r',' ','N','e','w',0},
496 {'A','r','i','a','l',0}, 162
497 },
499 },
500 /* 18. Vietnamese (Windows) */
501 {
502 {
503 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
504 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
505 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
506 1258, 1258, {'V','i','e','t','n','a','m','e','s','e',' ','(','W','i','n','d','o','w','s',')',0},
507 {'w','i','n','d','o','w','s','-','1','2','5','8',0},
508 {'w','i','n','d','o','w','s','-','1','2','5','8',0},
509 {'w','i','n','d','o','w','s','-','1','2','5','8',0},
510 {'C','o','u','r','i','e','r',' ','N','e','w',0},
511 {'A','r','i','a','l',0}, 163
512 },
513 },
514 /* 19. Western European (Windows) */
515 {
516 {
517 MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
518 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
519 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
520 1252, 1252, {'W','e','s','t','e','r','n',' ','E','u','r','o','p','e','a','n',' ','(','W','i','n','d','o','w','s',')',0},
521 {'W','i','n','d','o','w','s','-','1','2','5','2',0},
522 {'W','i','n','d','o','w','s','-','1','2','5','2',0},
523 {'i','s','o','-','8','8','5','9','-','1',0},
524 {'C','o','u','r','i','e','r',' ','N','e','w',0},
525 {'A','r','i','a','l',0}, 0
526 },
528 },
529 /* 20. Unicode */
530 {
531 {
532 MIMECONTF_MINIMAL | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
533 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
534 1200, 1200, {'U','n','i','c','o','d','e',0},
535 {'u','n','i','c','o','d','e',0},
536 {'u','n','i','c','o','d','e',0},
537 {'u','n','i','c','o','d','e',0},
538 {'C','o','u','r','i','e','r',' ','N','e','w',0},
539 {'A','r','i','a','l',0}, 1
540 },
541 }
542};
543
545{
546 HMODULE hMlang;
547
548 hMlang = GetModuleHandleA("mlang.dll");
549 pConvertINetMultiByteToUnicode = (void *)GetProcAddress(hMlang, "ConvertINetMultiByteToUnicode");
550 pConvertINetUnicodeToMultiByte = (void *)GetProcAddress(hMlang, "ConvertINetUnicodeToMultiByte");
551 pRfc1766ToLcidA = (void *)GetProcAddress(hMlang, "Rfc1766ToLcidA");
552 pLcidToRfc1766A = (void *)GetProcAddress(hMlang, "LcidToRfc1766A");
553
554 pGetCPInfoExA = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetCPInfoExA");
555
556 return TRUE;
557}
558
559#define ok_w2(format, szString1, szString2) \
560\
561 if (lstrcmpW((szString1), (szString2)) != 0) \
562 { \
563 CHAR string1[256], string2[256]; \
564 WideCharToMultiByte(CP_ACP, 0, (szString1), -1, string1, 256, NULL, NULL); \
565 WideCharToMultiByte(CP_ACP, 0, (szString2), -1, string2, 256, NULL, NULL); \
566 ok(0, (format), string1, string2); \
567 }
568
569static void test_multibyte_to_unicode_translations(IMultiLanguage2 *iML2)
570{
571 /* these APIs are broken regarding constness of the input buffer */
572 char stringA[] = "Just a test string\0"; /* double 0 for CP_UNICODE tests */
573 WCHAR stringW[] = {'J','u','s','t',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
574 char bufA[256];
575 WCHAR bufW[256];
576 UINT lenA, lenW, expected_len;
577 HRESULT ret;
578
579 /* IMultiLanguage2_ConvertStringToUnicode tests */
580
581 memset(bufW, 'x', sizeof(bufW));
582 lenA = 0;
583 lenW = ARRAY_SIZE(bufW);
584 ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, bufW, &lenW);
585 ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret);
586 ok(lenA == 0, "expected lenA 0, got %u\n", lenA);
587 ok(lenW == 0, "expected lenW 0, got %u\n", lenW);
588
589 memset(bufW, 'x', sizeof(bufW));
590 lenA = -1;
591 lenW = ARRAY_SIZE(bufW);
592 ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, bufW, &lenW);
593 ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret);
594 ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA);
595 ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW);
596 if (lenW < ARRAY_SIZE(bufW)) {
597 /* can only happen if the convert call fails */
598 ok(bufW[lenW] != 0, "buf should not be 0 terminated\n");
599 bufW[lenW] = 0; /* -1 doesn't include 0 terminator */
600 }
601 ok(!lstrcmpW(bufW, stringW), "bufW/stringW mismatch\n");
602
603 memset(bufW, 'x', sizeof(bufW));
604 lenA = -1;
605 lenW = 5;
606 ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, bufW, &lenW);
607 ok(ret == E_FAIL, "IMultiLanguage2_ConvertStringToUnicode should fail: %08x\n", ret);
608 ok(lenW == 0, "expected lenW 0, got %u\n", lenW);
609 /* still has to do partial conversion */
610 ok(!memcmp(bufW, stringW, 5 * sizeof(WCHAR)), "bufW/stringW mismatch\n");
611
612 memset(bufW, 'x', sizeof(bufW));
613 lenA = -1;
614 lenW = ARRAY_SIZE(bufW);
615 ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, CP_UNICODE, stringA, &lenA, bufW, &lenW);
616 ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret);
617 ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA);
618 ok(lenW == lstrlenW(stringW)/(int)sizeof(WCHAR), "wrong lenW %u\n", lenW);
619 ok(bufW[lenW] != 0, "buf should not be 0 terminated\n");
620 bufW[lenW] = 0; /* -1 doesn't include 0 terminator */
621 ok(!lstrcmpA((LPCSTR)bufW, stringA), "bufW/stringA mismatch\n");
622
623 memset(bufW, 'x', sizeof(bufW));
624 lenA = lstrlenA(stringA);
625 lenW = 0;
626 ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, 1252, stringA, &lenA, NULL, &lenW);
627 ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08x\n", ret);
628 ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA);
629 expected_len = MultiByteToWideChar(1252, 0, stringA, lenA, NULL, 0);
630 ok(lenW == expected_len, "expected lenW %u, got %u\n", expected_len, lenW);
631
632 memset(bufW, 'x', sizeof(bufW));
633 lenA = lstrlenA(stringA);
634 lenW = ARRAY_SIZE(bufW);
635 ret = pConvertINetMultiByteToUnicode(NULL, 1252, stringA, (INT *)&lenA, NULL, (INT *)&lenW);
636 ok(ret == S_OK, "ConvertINetMultiByteToUnicode failed: %08x\n", ret);
637 ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA);
638 expected_len = MultiByteToWideChar(1252, 0, stringA, lenA, NULL, 0);
639 ok(lenW == expected_len, "expected lenW %u, got %u\n", expected_len, lenW);
640
641 memset(bufW, 'x', sizeof(bufW));
642 lenA = lstrlenA(stringA);
643 lenW = 0;
644 ret = pConvertINetMultiByteToUnicode(NULL, 1252, stringA, (INT *)&lenA, NULL, (INT *)&lenW);
645 ok(ret == S_OK, "ConvertINetMultiByteToUnicode failed: %08x\n", ret);
646 ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA);
647 expected_len = MultiByteToWideChar(1252, 0, stringA, lenA, NULL, 0);
648 ok(lenW == expected_len, "expected lenW %u, got %u\n", expected_len, lenW);
649
650 /* IMultiLanguage2_ConvertStringFromUnicode tests */
651
652 memset(bufA, 'x', sizeof(bufA));
653 lenW = 0;
654 lenA = sizeof(bufA);
655 ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, bufA, &lenA);
656 ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret);
657 ok(lenA == 0, "expected lenA 0, got %u\n", lenA);
658 ok(lenW == 0, "expected lenW 0, got %u\n", lenW);
659
660 memset(bufA, 'x', sizeof(bufA));
661 lenW = -1;
662 lenA = sizeof(bufA);
663 ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, bufA, &lenA);
664 ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret);
665 ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA);
666 ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW);
667 ok(bufA[lenA] != 0, "buf should not be 0 terminated\n");
668 bufA[lenA] = 0; /* -1 doesn't include 0 terminator */
669 ok(!lstrcmpA(bufA, stringA), "bufA/stringA mismatch\n");
670
671 memset(bufA, 'x', sizeof(bufA));
672 lenW = -1;
673 lenA = 5;
674 ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, bufA, &lenA);
675 ok(ret == E_FAIL, "IMultiLanguage2_ConvertStringFromUnicode should fail: %08x\n", ret);
676 ok(lenA == 0, "expected lenA 0, got %u\n", lenA);
677 /* still has to do partial conversion */
678 ok(!memcmp(bufA, stringA, 5), "bufW/stringW mismatch\n");
679
680 memset(bufA, 'x', sizeof(bufA));
681 lenW = -1;
682 lenA = sizeof(bufA);
683 ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, CP_UNICODE, stringW, &lenW, bufA, &lenA);
684 ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret);
685 ok(lenA == lstrlenA(stringA) * (int)sizeof(WCHAR), "wrong lenA %u\n", lenA);
686 ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW);
687 ok(bufA[lenA] != 0 && bufA[lenA+1] != 0, "buf should not be 0 terminated\n");
688 bufA[lenA] = 0; /* -1 doesn't include 0 terminator */
689 bufA[lenA+1] = 0; /* sizeof(WCHAR) */
690 ok(!lstrcmpW((LPCWSTR)bufA, stringW), "bufA/stringW mismatch\n");
691
692 memset(bufA, 'x', sizeof(bufA));
693 lenW = lstrlenW(stringW);
694 lenA = 0;
695 ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, stringW, &lenW, NULL, &lenA);
696 ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08x\n", ret);
697 ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW);
698 expected_len = WideCharToMultiByte(1252, 0, stringW, lenW, NULL, 0, NULL, NULL);
699 ok(lenA == expected_len, "expected lenA %u, got %u\n", expected_len, lenA);
700}
701
702static void cpinfo_cmp(MIMECPINFO *cpinfo1, MIMECPINFO *cpinfo2)
703{
704 ok(cpinfo1->dwFlags == cpinfo2->dwFlags, "dwFlags mismatch: %08x != %08x\n", cpinfo1->dwFlags, cpinfo2->dwFlags);
705 ok(cpinfo1->uiCodePage == cpinfo2->uiCodePage, "uiCodePage mismatch: %u != %u\n", cpinfo1->uiCodePage, cpinfo2->uiCodePage);
706 ok(cpinfo1->uiFamilyCodePage == cpinfo2->uiFamilyCodePage, "uiFamilyCodePage mismatch: %u != %u\n", cpinfo1->uiFamilyCodePage, cpinfo2->uiFamilyCodePage);
707 ok(!lstrcmpW(cpinfo1->wszDescription, cpinfo2->wszDescription), "wszDescription mismatch\n");
708 ok(!lstrcmpW(cpinfo1->wszWebCharset, cpinfo2->wszWebCharset), "wszWebCharset mismatch\n");
709 ok(!lstrcmpW(cpinfo1->wszHeaderCharset, cpinfo2->wszHeaderCharset), "wszHeaderCharset mismatch\n");
710 ok(!lstrcmpW(cpinfo1->wszBodyCharset, cpinfo2->wszBodyCharset), "wszBodyCharset mismatch\n");
711 ok(!lstrcmpW(cpinfo1->wszFixedWidthFont, cpinfo2->wszFixedWidthFont), "wszFixedWidthFont mismatch\n");
712 ok(!lstrcmpW(cpinfo1->wszProportionalFont, cpinfo2->wszProportionalFont), "wszProportionalFont mismatch\n");
713 ok(cpinfo1->bGDICharset == cpinfo2->bGDICharset, "bGDICharset mismatch: %d != %d\n", cpinfo1->bGDICharset, cpinfo2->bGDICharset);
714}
715
716#ifdef DUMP_CP_INFO
717static const char *dump_mime_flags(DWORD flags)
718{
719 static char buf[1024];
720
721 buf[0] = 0;
722
723 if (flags & MIMECONTF_MAILNEWS) strcat(buf, " MIMECONTF_MAILNEWS");
724 if (flags & MIMECONTF_BROWSER) strcat(buf, " MIMECONTF_BROWSER");
725 if (flags & MIMECONTF_MINIMAL) strcat(buf, " MIMECONTF_MINIMAL");
726 if (flags & MIMECONTF_IMPORT) strcat(buf, " MIMECONTF_IMPORT");
727 if (flags & MIMECONTF_SAVABLE_MAILNEWS) strcat(buf, " MIMECONTF_SAVABLE_MAILNEWS");
728 if (flags & MIMECONTF_SAVABLE_BROWSER) strcat(buf, " MIMECONTF_SAVABLE_BROWSER");
729 if (flags & MIMECONTF_EXPORT) strcat(buf, " MIMECONTF_EXPORT");
730 if (flags & MIMECONTF_PRIVCONVERTER) strcat(buf, " MIMECONTF_PRIVCONVERTER");
731 if (flags & MIMECONTF_VALID) strcat(buf, " MIMECONTF_VALID");
732 if (flags & MIMECONTF_VALID_NLS) strcat(buf, " MIMECONTF_VALID_NLS");
733 if (flags & MIMECONTF_MIME_IE4) strcat(buf, " MIMECONTF_MIME_IE4");
734 if (flags & MIMECONTF_MIME_LATEST) strcat(buf, " MIMECONTF_MIME_LATEST");
735 if (flags & MIMECONTF_MIME_REGISTRY) strcat(buf, " MIMECONTF_MIME_REGISTRY");
736
737 return buf;
738}
739#endif
740
741static HRESULT check_convertible(IMultiLanguage2 *iML2, UINT from, UINT to)
742{
745 HRESULT hr;
746 UINT srcsz, destsz;
747
748 static WCHAR strW[] = {'a','b','c',0};
749
750 /* Check to see if the target codepage has these characters or not */
751 if (from != CP_UTF8)
752 {
753 BOOL fDefaultChar;
754 char ch[10];
755 int cb;
757 strW, 3, ch, sizeof(ch), NULL, &fDefaultChar);
758
759 if(cb == 0 || fDefaultChar)
760 {
761 trace("target codepage %i does not contain 'abc'\n",from);
762 return E_FAIL;
763 }
764 }
765
766 srcsz = lstrlenW(strW) + 1;
767 destsz = MAX_PATH;
768 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, from, strW,
769 &srcsz, convert, &destsz);
770 if (hr != S_OK)
771 return S_FALSE;
772
773 srcsz = -1;
774 destsz = MAX_PATH;
775 hr = IMultiLanguage2_ConvertString(iML2, NULL, from, to, (BYTE *)convert,
776 &srcsz, dest, &destsz);
777 if (hr != S_OK)
778 return S_FALSE;
779
780 return S_OK;
781}
782
783static void test_EnumCodePages(IMultiLanguage2 *iML2, DWORD flags)
784{
785 IEnumCodePage *iEnumCP = NULL;
786 MIMECPINFO *cpinfo;
787 MIMECPINFO cpinfo2;
788 HRESULT ret;
789 ULONG i, n;
790 UINT total;
791
792 total = 0;
793 ret = IMultiLanguage2_GetNumberOfCodePageInfo(iML2, &total);
794 ok(ret == S_OK && total != 0, "IMultiLanguage2_GetNumberOfCodePageInfo: expected S_OK/!0, got %08x/%u\n", ret, total);
795
796 trace("total mlang supported codepages %u\n", total);
797
798 ret = IMultiLanguage2_EnumCodePages(iML2, flags, LANG_NEUTRAL, &iEnumCP);
799 ok(ret == S_OK && iEnumCP, "IMultiLanguage2_EnumCodePages: expected S_OK/!NULL, got %08x/%p\n", ret, iEnumCP);
800
801 ret = IEnumCodePage_Reset(iEnumCP);
802 ok(ret == S_OK, "IEnumCodePage_Reset: expected S_OK, got %08x\n", ret);
803 n = 65536;
804 ret = IEnumCodePage_Next(iEnumCP, 0, NULL, &n);
805 ok(ret == S_FALSE || ret == E_FAIL,
806 "IEnumCodePage_Next: expected S_FALSE or E_FAIL, got %08x\n", ret);
807 if (ret == S_FALSE)
808 ok(n == 0, "IEnumCodePage_Next: expected 0/S_FALSE, got %u/%08x\n", n, ret);
809 else if (ret == E_FAIL)
810 ok(n == 65536, "IEnumCodePage_Next: expected 65536/E_FAIL, got %u/%08x\n", n, ret);
811 ret = IEnumCodePage_Next(iEnumCP, 0, NULL, NULL);
812 ok(ret == S_FALSE || ret == E_FAIL,
813 "IEnumCodePage_Next: expected S_FALSE or E_FAIL, got %08x\n", ret);
814
815 cpinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*cpinfo) * total * 2);
816
817 n = total * 2;
818 ret = IEnumCodePage_Next(iEnumCP, 0, cpinfo, &n);
819 ok(ret == S_FALSE && n == 0, "IEnumCodePage_Next: expected S_FALSE/0, got %08x/%u\n", ret, n);
820
821 n = total * 2;
822 ret = IEnumCodePage_Next(iEnumCP, n, cpinfo, &n);
823 ok(ret == S_OK && n != 0, "IEnumCodePage_Next: expected S_OK/!0, got %08x/%u\n", ret, n);
824
825 trace("flags %08x, enumerated codepages %u\n", flags, n);
826
827 if (!flags)
828 {
829 ok(n == total, "IEnumCodePage_Next: expected %u, got %u\n", total, n);
830
831 flags = MIMECONTF_MIME_LATEST;
832 }
833
834 total = n;
835
836 for (i = 0; i < n; i++)
837 {
838 CHARSETINFO csi;
839 MIMECSETINFO mcsi;
840 HRESULT convertible = S_OK;
841 static const WCHAR autoW[] = {'_','a','u','t','o',0};
842 static const WCHAR feffW[] = {'u','n','i','c','o','d','e','F','E','F','F',0};
843
844#ifdef DUMP_CP_INFO
845 trace("MIMECPINFO #%u:\n"
846 "dwFlags %08x %s\n"
847 "uiCodePage %u\n"
848 "uiFamilyCodePage %u\n"
849 "wszDescription %s\n"
850 "wszWebCharset %s\n"
851 "wszHeaderCharset %s\n"
852 "wszBodyCharset %s\n"
853 "wszFixedWidthFont %s\n"
854 "wszProportionalFont %s\n"
855 "bGDICharset %d\n\n",
856 i,
857 cpinfo[i].dwFlags, dump_mime_flags(cpinfo[i].dwFlags),
858 cpinfo[i].uiCodePage,
859 cpinfo[i].uiFamilyCodePage,
860 wine_dbgstr_w(cpinfo[i].wszDescription),
861 wine_dbgstr_w(cpinfo[i].wszWebCharset),
862 wine_dbgstr_w(cpinfo[i].wszHeaderCharset),
863 wine_dbgstr_w(cpinfo[i].wszBodyCharset),
864 wine_dbgstr_w(cpinfo[i].wszFixedWidthFont),
865 wine_dbgstr_w(cpinfo[i].wszProportionalFont),
866 cpinfo[i].bGDICharset);
867#endif
868 ok(cpinfo[i].dwFlags & flags, "enumerated flags %08x do not include requested %08x\n", cpinfo[i].dwFlags, flags);
869
870 if (TranslateCharsetInfo((DWORD *)(INT_PTR)cpinfo[i].uiFamilyCodePage, &csi, TCI_SRCCODEPAGE))
871 ok(cpinfo[i].bGDICharset == csi.ciCharset, "%d != %d\n", cpinfo[i].bGDICharset, csi.ciCharset);
872 else
873 if (winetest_debug > 1)
874 trace("TranslateCharsetInfo failed for cp %u\n", cpinfo[i].uiFamilyCodePage);
875
876#ifdef DUMP_CP_INFO
877 trace("%u: codepage %u family %u\n", i, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage);
878#endif
879
880 /* support files for some codepages might be not installed, or
881 * the codepage is just an alias.
882 */
883 if (IsValidCodePage(cpinfo[i].uiCodePage))
884 {
885 ret = IMultiLanguage2_IsConvertible(iML2, cpinfo[i].uiCodePage, CP_UNICODE);
886 ok(ret == S_OK, "IMultiLanguage2_IsConvertible(%u -> CP_UNICODE) = %08x\n", cpinfo[i].uiCodePage, ret);
887 ret = IMultiLanguage2_IsConvertible(iML2, CP_UNICODE, cpinfo[i].uiCodePage);
888 ok(ret == S_OK, "IMultiLanguage2_IsConvertible(CP_UNICODE -> %u) = %08x\n", cpinfo[i].uiCodePage, ret);
889
890 convertible = check_convertible(iML2, cpinfo[i].uiCodePage, CP_UTF8);
891 if (convertible != E_FAIL)
892 {
893 ret = IMultiLanguage2_IsConvertible(iML2, cpinfo[i].uiCodePage, CP_UTF8);
894 ok(ret == convertible, "IMultiLanguage2_IsConvertible(%u -> CP_UTF8) = %08x\n", cpinfo[i].uiCodePage, ret);
895 ret = IMultiLanguage2_IsConvertible(iML2, CP_UTF8, cpinfo[i].uiCodePage);
896 ok(ret == convertible, "IMultiLanguage2_IsConvertible(CP_UTF8 -> %u) = %08x\n", cpinfo[i].uiCodePage, ret);
897 }
898 }
899 else
900 if (winetest_debug > 1)
901 trace("IsValidCodePage failed for cp %u\n", cpinfo[i].uiCodePage);
902
903 if (memcmp(cpinfo[i].wszWebCharset,feffW,sizeof(WCHAR)*11)==0)
904 skip("Legacy windows bug returning invalid charset of unicodeFEFF\n");
905 else
906 {
907 ret = IMultiLanguage2_GetCharsetInfo(iML2, cpinfo[i].wszWebCharset, &mcsi);
908 /* _autoxxx charsets are a fake and GetCharsetInfo fails for them */
909 if (memcmp(cpinfo[i].wszWebCharset, autoW, 5 * sizeof(WCHAR)))
910 {
911 ok (ret == S_OK, "IMultiLanguage2_GetCharsetInfo failed: %08x\n", ret);
912#ifdef DUMP_CP_INFO
913 trace("%s: %u %u %s\n", wine_dbgstr_w(cpinfo[i].wszWebCharset), mcsi.uiCodePage, mcsi.uiInternetEncoding, wine_dbgstr_w(mcsi.wszCharset));
914#endif
915 ok(!lstrcmpiW(cpinfo[i].wszWebCharset, mcsi.wszCharset), "%s != %s\n",
916 wine_dbgstr_w(cpinfo[i].wszWebCharset), wine_dbgstr_w(mcsi.wszCharset));
917
918 if (0)
919 {
920 /* native mlang returns completely messed up encodings in some cases */
921 ok(mcsi.uiInternetEncoding == cpinfo[i].uiCodePage || mcsi.uiInternetEncoding == cpinfo[i].uiFamilyCodePage,
922 "%u != %u || %u\n", mcsi.uiInternetEncoding, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage);
923 ok(mcsi.uiCodePage == cpinfo[i].uiCodePage || mcsi.uiCodePage == cpinfo[i].uiFamilyCodePage,
924 "%u != %u || %u\n", mcsi.uiCodePage, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage);
925 }
926 }
927 }
928
929 if (memcmp(cpinfo[i].wszHeaderCharset,feffW,sizeof(WCHAR)*11)==0)
930 skip("Legacy windows bug returning invalid charset of unicodeFEFF\n");
931 else
932 {
933 ret = IMultiLanguage2_GetCharsetInfo(iML2, cpinfo[i].wszHeaderCharset, &mcsi);
934 /* _autoxxx charsets are a fake and GetCharsetInfo fails for them */
935 if (memcmp(cpinfo[i].wszHeaderCharset, autoW, 5 * sizeof(WCHAR)))
936 {
937 ok (ret == S_OK, "IMultiLanguage2_GetCharsetInfo failed: %08x\n", ret);
938#ifdef DUMP_CP_INFO
939 trace("%s: %u %u %s\n", wine_dbgstr_w(cpinfo[i].wszHeaderCharset), mcsi.uiCodePage, mcsi.uiInternetEncoding, wine_dbgstr_w(mcsi.wszCharset));
940#endif
941 ok(!lstrcmpiW(cpinfo[i].wszHeaderCharset, mcsi.wszCharset), "%s != %s\n",
942 wine_dbgstr_w(cpinfo[i].wszHeaderCharset), wine_dbgstr_w(mcsi.wszCharset));
943
944 if (0)
945 {
946 /* native mlang returns completely messed up encodings in some cases */
947 ok(mcsi.uiInternetEncoding == cpinfo[i].uiCodePage || mcsi.uiInternetEncoding == cpinfo[i].uiFamilyCodePage,
948 "%u != %u || %u\n", mcsi.uiInternetEncoding, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage);
949 ok(mcsi.uiCodePage == cpinfo[i].uiCodePage || mcsi.uiCodePage == cpinfo[i].uiFamilyCodePage,
950 "%u != %u || %u\n", mcsi.uiCodePage, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage);
951 }
952 }
953 }
954
955 if (memcmp(cpinfo[i].wszBodyCharset,feffW,sizeof(WCHAR)*11)==0)
956 skip("Legacy windows bug returning invalid charset of unicodeFEFF\n");
957 else
958 {
959 ret = IMultiLanguage2_GetCharsetInfo(iML2, cpinfo[i].wszBodyCharset, &mcsi);
960 /* _autoxxx charsets are a fake and GetCharsetInfo fails for them */
961 if (memcmp(cpinfo[i].wszBodyCharset, autoW, 5 * sizeof(WCHAR)))
962 {
963 ok (ret == S_OK, "IMultiLanguage2_GetCharsetInfo failed: %08x\n", ret);
964#ifdef DUMP_CP_INFO
965 trace("%s: %u %u %s\n", wine_dbgstr_w(cpinfo[i].wszBodyCharset), mcsi.uiCodePage, mcsi.uiInternetEncoding, wine_dbgstr_w(mcsi.wszCharset));
966#endif
967 ok(!lstrcmpiW(cpinfo[i].wszBodyCharset, mcsi.wszCharset), "%s != %s\n",
968 wine_dbgstr_w(cpinfo[i].wszBodyCharset), wine_dbgstr_w(mcsi.wszCharset));
969
970 if (0)
971 {
972 /* native mlang returns completely messed up encodings in some cases */
973 ok(mcsi.uiInternetEncoding == cpinfo[i].uiCodePage || mcsi.uiInternetEncoding == cpinfo[i].uiFamilyCodePage,
974 "%u != %u || %u\n", mcsi.uiInternetEncoding, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage);
975 ok(mcsi.uiCodePage == cpinfo[i].uiCodePage || mcsi.uiCodePage == cpinfo[i].uiFamilyCodePage,
976 "%u != %u || %u\n", mcsi.uiCodePage, cpinfo[i].uiCodePage, cpinfo[i].uiFamilyCodePage);
977 }
978 }
979 }
980 }
981
982 /* now IEnumCodePage_Next should fail, since pointer is at the end */
983 n = 1;
984 ret = IEnumCodePage_Next(iEnumCP, 1, &cpinfo2, &n);
985 ok(ret == S_FALSE && n == 0, "IEnumCodePage_Next: expected S_FALSE/0, got %08x/%u\n", ret, n);
986
987 ret = IEnumCodePage_Reset(iEnumCP);
988 ok(ret == S_OK, "IEnumCodePage_Reset: expected S_OK, got %08x\n", ret);
989 n = 0;
990 ret = IEnumCodePage_Next(iEnumCP, 1, &cpinfo2, &n);
991 ok(n == 1 && ret == S_OK, "IEnumCodePage_Next: expected 1/S_OK, got %u/%08x\n", n, ret);
992 cpinfo_cmp(cpinfo, &cpinfo2);
993
994 if (0)
995 {
996 /* Due to a bug in MS' implementation of IEnumCodePage_Skip
997 * it's not used here.
998 */
999 ret = IEnumCodePage_Skip(iEnumCP, 1);
1000 ok(ret == S_OK, "IEnumCodePage_Skip: expected S_OK, got %08x\n", ret);
1001 }
1002 for (i = 0; i < total - 1; i++)
1003 {
1004 n = 0;
1005 ret = IEnumCodePage_Next(iEnumCP, 1, &cpinfo2, &n);
1006 ok(n == 1 && ret == S_OK, "IEnumCodePage_Next: expected 1/S_OK, got %u/%08x\n", n, ret);
1007 cpinfo_cmp(&cpinfo[i + 1], &cpinfo2);
1008 }
1009
1011 IEnumCodePage_Release(iEnumCP);
1012}
1013
1014static void test_GetCharsetInfo_other(IMultiLanguage *ml)
1015{
1016 WCHAR asciiW[] = {'a','s','c','i','i',0};
1017 WCHAR iso88591_1W[] = {'I','S','O','-','8','8','5','9','-','1',0};
1018 WCHAR iso88591_1retW[] = {'i','s','o','-','8','8','5','9','-','1',0};
1019 WCHAR iso88591_2W[] = {'I','S','O','8','8','5','9','-','1',0};
1020 WCHAR iso88591_2retW[] = {'i','s','o','8','8','5','9','-','1',0};
1021 WCHAR iso88591_3W[] = {'I','S','O','8','8','5','9','1',0};
1022 WCHAR iso88591_4W[] = {'I','S','O','-','8','8','5','9','1',0};
1023 WCHAR iso88591_5W[] = {'I','S','O','8','8','-','5','9','1',0};
1024 WCHAR iso88591_6W[] = {'-','I','S','O','8','8','5','9','1',0};
1025 WCHAR iso88591_7W[] = {' ','I','S','O','-','8','8','5','9','-','1',0};
1026 struct other {
1027 int todo;
1028 HRESULT hr;
1029 WCHAR* charset;
1030 WCHAR* ret_charset;
1031 } other[] = {
1032 { 0, S_OK, asciiW, asciiW },
1033 { 0, S_OK, iso88591_1W, iso88591_1retW },
1034 { 1, S_OK, iso88591_2W, iso88591_2retW },
1035 { 0, E_FAIL, iso88591_3W, 0 },
1036 { 0, E_FAIL, iso88591_4W, 0 },
1037 { 0, E_FAIL, iso88591_5W, 0 },
1038 { 0, E_FAIL, iso88591_6W, 0 },
1039 { 0, E_FAIL, iso88591_7W, 0 },
1040 };
1041 MIMECSETINFO info;
1042 HRESULT hr;
1043 int i;
1044
1045 for (i = 0; i < ARRAY_SIZE(other); i++)
1046 {
1047 hr = IMultiLanguage_GetCharsetInfo(ml, other[i].charset, &info);
1048
1050 ok(hr == other[i].hr, "#%d: got %08x, expected %08x\n", i, hr, other[i].hr);
1051
1052 if (hr == S_OK)
1054 ok(!lstrcmpW(info.wszCharset, other[i].ret_charset), "#%d: got %s, expected %s\n",
1055 i, wine_dbgstr_w(info.wszCharset), wine_dbgstr_w(other[i].ret_charset));
1056 }
1057}
1058
1059static void scriptinfo_cmp(SCRIPTINFO *sinfo1, SCRIPTINFO *sinfo2)
1060{
1061 ok(sinfo1->ScriptId == sinfo2->ScriptId, "ScriptId mismatch: %d != %d\n", sinfo1->ScriptId, sinfo2->ScriptId);
1062 ok(sinfo1->uiCodePage == sinfo2->uiCodePage, "uiCodePage mismatch: %u != %u\n", sinfo1->uiCodePage, sinfo2->uiCodePage);
1063 ok(!lstrcmpW(sinfo1->wszDescription, sinfo2->wszDescription), "wszDescription mismatch\n");
1064 ok(!lstrcmpW(sinfo1->wszFixedWidthFont, sinfo2->wszFixedWidthFont), "wszFixedWidthFont mismatch\n");
1065 ok(!lstrcmpW(sinfo1->wszProportionalFont, sinfo2->wszProportionalFont), "wszProportionalFont mismatch\n");
1066}
1067
1068static void test_EnumScripts(IMultiLanguage2 *iML2, DWORD flags)
1069{
1070 IEnumScript *iEnumScript = NULL;
1071 SCRIPTINFO *sinfo;
1072 SCRIPTINFO sinfo2;
1073 HRESULT ret;
1074 ULONG i, n;
1075 UINT total;
1076
1077 total = 0;
1078 ret = IMultiLanguage2_GetNumberOfScripts(iML2, &total);
1079 ok(ret == S_OK && total != 0, "IMultiLanguage2_GetNumberOfScripts: expected S_OK/!0, got %08x/%u\n", ret, total);
1080
1081 trace("total mlang supported scripts %u\n", total);
1082
1083 ret = IMultiLanguage2_EnumScripts(iML2, flags, LANG_NEUTRAL, &iEnumScript);
1084 ok(ret == S_OK && iEnumScript, "IMultiLanguage2_EnumScripts: expected S_OK/!NULL, got %08x/%p\n", ret, iEnumScript);
1085
1086 ret = IEnumScript_Reset(iEnumScript);
1087 ok(ret == S_OK, "IEnumScript_Reset: expected S_OK, got %08x\n", ret);
1088 n = 65536;
1089 ret = IEnumScript_Next(iEnumScript, 0, NULL, &n);
1090 ok(n == 65536 && ret == E_FAIL, "IEnumScript_Next: expected 65536/E_FAIL, got %u/%08x\n", n, ret);
1091 ret = IEnumScript_Next(iEnumScript, 0, NULL, NULL);
1092 ok(ret == E_FAIL, "IEnumScript_Next: expected E_FAIL, got %08x\n", ret);
1093
1094 sinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*sinfo) * total * 2);
1095
1096 n = total * 2;
1097 ret = IEnumScript_Next(iEnumScript, 0, sinfo, &n);
1098 ok(ret == S_FALSE && n == 0, "IEnumScript_Next: expected S_FALSE/0, got %08x/%u\n", ret, n);
1099
1100 n = total * 2;
1101 ret = IEnumScript_Next(iEnumScript, n, sinfo, &n);
1102 ok(ret == S_OK && n != 0, "IEnumScript_Next: expected S_OK, got %08x/%u\n", ret, n);
1103
1104 trace("flags %08x, enumerated scripts %u\n", flags, n);
1105
1106 if (!flags)
1107 {
1108 ok(n == total, "IEnumScript_Next: expected %u, got %u\n", total, n);
1109 }
1110
1111 total = n;
1112
1113 for (i = 0; pGetCPInfoExA && i < n; i++)
1114 {
1115#ifdef DUMP_SCRIPT_INFO
1116 trace("SCRIPTINFO #%u:\n"
1117 "ScriptId %08x\n"
1118 "uiCodePage %u\n"
1119 "wszDescription %s\n"
1120 "wszFixedWidthFont %s\n"
1121 "wszProportionalFont %s\n\n",
1122 i,
1123 sinfo[i].ScriptId,
1124 sinfo[i].uiCodePage,
1125 wine_dbgstr_w(sinfo[i].wszDescription),
1126 wine_dbgstr_w(sinfo[i].wszFixedWidthFont),
1127 wine_dbgstr_w(sinfo[i].wszProportionalFont));
1128 trace("%u codepage %u\n", i, sinfo[i].uiCodePage);
1129#endif
1130 }
1131
1132 /* now IEnumScript_Next should fail, since pointer is at the end */
1133 n = 1;
1134 ret = IEnumScript_Next(iEnumScript, 1, &sinfo2, &n);
1135 ok(ret == S_FALSE && n == 0, "IEnumScript_Next: expected S_FALSE/0, got %08x/%u\n", ret, n);
1136
1137 ret = IEnumScript_Reset(iEnumScript);
1138 ok(ret == S_OK, "IEnumScript_Reset: expected S_OK, got %08x\n", ret);
1139 n = 0;
1140 ret = IEnumScript_Next(iEnumScript, 1, &sinfo2, &n);
1141 ok(n == 1 && ret == S_OK, "IEnumScript_Next: expected 1/S_OK, got %u/%08x\n", n, ret);
1142 scriptinfo_cmp(sinfo, &sinfo2);
1143
1144 if (0)
1145 {
1146 /* Due to a bug in MS' implementation of IEnumScript_Skip
1147 * it's not used here.
1148 */
1149 ret = IEnumScript_Skip(iEnumScript, 1);
1150 ok(ret == S_OK, "IEnumScript_Skip: expected S_OK, got %08x\n", ret);
1151 }
1152 for (i = 0; i < total - 1; i++)
1153 {
1154 n = 0;
1155 ret = IEnumScript_Next(iEnumScript, 1, &sinfo2, &n);
1156 ok(n == 1 && ret == S_OK, "IEnumScript_Next: expected 1/S_OK, got %u/%08x\n", n, ret);
1157 scriptinfo_cmp(&sinfo[i + 1], &sinfo2);
1158 }
1159
1161 IEnumScript_Release(iEnumScript);
1162}
1163
1164static void IMLangFontLink_Test(IMLangFontLink* iMLFL)
1165{
1166 DWORD dwCodePages, dwManyCodePages;
1167 DWORD dwCmpCodePages;
1168 UINT CodePage;
1169 static const WCHAR str[] = { 'd', 0x0436, 0xff90 };
1171 HRESULT ret;
1172
1173 dwCodePages = ~0u;
1174 ret = IMLangFontLink_CodePageToCodePages(iMLFL, -1, &dwCodePages);
1175 ok(ret == E_FAIL, "IMLangFontLink_CodePageToCodePages should fail: %x\n", ret);
1176 ok(dwCodePages == 0, "expected 0, got %u\n", dwCodePages);
1177
1178 dwCodePages = 0;
1179 ret = IMLangFontLink_CodePageToCodePages(iMLFL, 932, &dwCodePages);
1180 ok(ret == S_OK, "IMLangFontLink_CodePageToCodePages error %x\n", ret);
1181 ok(dwCodePages == FS_JISJAPAN, "expected FS_JISJAPAN, got %08x\n", dwCodePages);
1182 CodePage = 0;
1183 ret = IMLangFontLink_CodePagesToCodePage(iMLFL, dwCodePages, 1035, &CodePage);
1184 ok(ret == S_OK, "IMLangFontLink_CodePagesToCodePage error %x\n", ret);
1185 ok(CodePage == 932, "Incorrect CodePage Returned (%i)\n",CodePage);
1186
1187 dwManyCodePages = 0;
1188 ret = IMLangFontLink_CodePageToCodePages(iMLFL, 1252, &dwManyCodePages);
1189 ok(ret == S_OK, "IMLangFontLink_CodePageToCodePages error %x\n", ret);
1190 ok(dwManyCodePages == FS_LATIN1, "expected FS_LATIN1, got %08x\n", dwManyCodePages);
1191 dwCodePages = 0;
1192 ret = IMLangFontLink_CodePageToCodePages(iMLFL, 1256, &dwCodePages);
1193 ok(ret == S_OK, "IMLangFontLink_CodePageToCodePages error %x\n", ret);
1194 ok(dwCodePages == FS_ARABIC, "expected FS_ARABIC, got %08x\n", dwCodePages);
1195 dwManyCodePages |= dwCodePages;
1196 ret = IMLangFontLink_CodePageToCodePages(iMLFL, 874, &dwCodePages);
1197 ok(ret == S_OK, "IMLangFontLink_CodePageToCodePages error %x\n", ret);
1198 ok(dwCodePages == FS_THAI, "expected FS_THAI, got %08x\n", dwCodePages);
1199 dwManyCodePages |= dwCodePages;
1200
1201 ret = IMLangFontLink_CodePagesToCodePage(iMLFL, dwManyCodePages, 1256, &CodePage);
1202 ok(ret == S_OK, "IMLangFontLink_CodePagesToCodePage error %x\n", ret);
1203 ok(CodePage == 1256, "Incorrect CodePage Returned (%i)\n",CodePage);
1204
1205 ret = IMLangFontLink_CodePagesToCodePage(iMLFL, dwManyCodePages, 936, &CodePage);
1206 ok(ret == S_OK, "IMLangFontLink_CodePagesToCodePage error %x\n", ret);
1207 ok(CodePage == 1252, "Incorrect CodePage Returned (%i)\n",CodePage);
1208
1209 /* Tests for GetCharCodePages */
1210
1211 /* Latin 1 */
1212 dwCmpCodePages = FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC | FS_GREEK | FS_TURKISH
1215 ret = IMLangFontLink_GetCharCodePages(iMLFL, 'd', &dwCodePages);
1216 ok(ret == S_OK, "IMLangFontLink_GetCharCodePages error %x\n", ret);
1217 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1218
1219 dwCodePages = 0;
1220 processed = 0;
1221 ret = IMLangFontLink_GetStrCodePages(iMLFL, str, 1, 0, &dwCodePages, &processed);
1222 ok(ret == S_OK, "IMLangFontLink_GetStrCodePages error %x\n", ret);
1223 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1224 ok(processed == 1, "expected 1, got %d\n", processed);
1225
1226 /* Cyrillic */
1227 dwCmpCodePages = FS_CYRILLIC | FS_JISJAPAN | FS_CHINESESIMP | FS_WANSUNG;
1228 ret = IMLangFontLink_GetCharCodePages(iMLFL, 0x0436, &dwCodePages);
1229 ok(ret == S_OK, "IMLangFontLink_GetCharCodePages error %x\n", ret);
1230 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1231
1232 dwCodePages = 0;
1233 processed = 0;
1234 ret = IMLangFontLink_GetStrCodePages(iMLFL, &str[1], 1, 0, &dwCodePages, &processed);
1235 ok(ret == S_OK, "IMLangFontLink_GetStrCodePages error %x\n", ret);
1236 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1237 ok(processed == 1, "expected 1, got %d\n", processed);
1238
1239 /* Japanese */
1240 dwCmpCodePages = FS_JISJAPAN;
1241 ret = IMLangFontLink_GetCharCodePages(iMLFL, 0xff90, &dwCodePages);
1242 ok(ret == S_OK, "IMLangFontLink_GetCharCodePages error %x\n", ret);
1243 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1244
1245 dwCodePages = 0;
1246 processed = 0;
1247 ret = IMLangFontLink_GetStrCodePages(iMLFL, &str[2], 1, 0, &dwCodePages, &processed);
1248 ok(ret == S_OK, "IMLangFontLink_GetStrCodePages error %x\n", ret);
1249 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1250 ok(processed == 1, "expected 1, got %d\n", processed);
1251
1252 dwCmpCodePages = FS_CYRILLIC | FS_JISJAPAN | FS_CHINESESIMP | FS_WANSUNG;
1253 dwCodePages = 0;
1254 processed = 0;
1255 ret = IMLangFontLink_GetStrCodePages(iMLFL, str, 2, 0, &dwCodePages, &processed);
1256 ok(ret == S_OK, "IMLangFontLink_GetStrCodePages error %x\n", ret);
1257 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1258 ok(processed == 2, "expected 2, got %d\n", processed);
1259
1260 dwCmpCodePages = FS_JISJAPAN;
1261 dwCodePages = 0;
1262 processed = 0;
1263 ret = IMLangFontLink_GetStrCodePages(iMLFL, str, 3, 0, &dwCodePages, &processed);
1264 ok(ret == S_OK, "IMLangFontLink_GetStrCodePages error %x\n", ret);
1265 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1266 ok(processed == 3, "expected 3, got %d\n", processed);
1267
1268 dwCodePages = 0xffff;
1269 processed = -1;
1270 ret = IMLangFontLink_GetStrCodePages(iMLFL, &str[2], 1, 0, &dwCodePages, &processed);
1271 ok(ret == S_OK, "IMLangFontLink_GetStrCodePages error %x\n", ret);
1272 ok(dwCodePages == dwCmpCodePages, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1273 ok(processed == 1, "expected 0, got %d\n", processed);
1274
1275 ret = IMLangFontLink_GetStrCodePages(iMLFL, &str[2], 1, 0, NULL, NULL);
1276 ok(ret == S_OK, "IMLangFontLink_GetStrCodePages error %x\n", ret);
1277
1278 dwCodePages = 0xffff;
1279 processed = -1;
1280 ret = IMLangFontLink_GetStrCodePages(iMLFL, str, -1, 0, &dwCodePages, &processed);
1281 ok(ret == E_INVALIDARG, "IMLangFontLink_GetStrCodePages should fail: %x\n", ret);
1282 ok(dwCodePages == 0, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1283 ok(processed == 0, "expected 0, got %d\n", processed);
1284
1285 dwCodePages = 0xffff;
1286 processed = -1;
1287 ret = IMLangFontLink_GetStrCodePages(iMLFL, NULL, 1, 0, &dwCodePages, &processed);
1288 ok(ret == E_INVALIDARG, "IMLangFontLink_GetStrCodePages should fail: %x\n", ret);
1289 ok(dwCodePages == 0, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1290 ok(processed == 0, "expected 0, got %d\n", processed);
1291
1292 dwCodePages = 0xffff;
1293 processed = -1;
1294 ret = IMLangFontLink_GetStrCodePages(iMLFL, str, 0, 0, &dwCodePages, &processed);
1295 ok(ret == E_INVALIDARG, "IMLangFontLink_GetStrCodePages should fail: %x\n", ret);
1296 ok(dwCodePages == 0, "expected %x, got %x\n", dwCmpCodePages, dwCodePages);
1297 ok(processed == 0, "expected 0, got %d\n", processed);
1298}
1299
1300/* copied from libs/wine/string.c */
1301static WCHAR *strstrW(const WCHAR *str, const WCHAR *sub)
1302{
1303 while (*str)
1304 {
1305 const WCHAR *p1 = str, *p2 = sub;
1306 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
1307 if (!*p2) return (WCHAR *)str;
1308 str++;
1309 }
1310 return NULL;
1311}
1312
1313static void test_rfc1766(IMultiLanguage2 *iML2)
1314{
1315 IEnumRfc1766 *pEnumRfc1766;
1316 RFC1766INFO info;
1317 ULONG n;
1318 HRESULT ret;
1319 BSTR rfcstr;
1320
1321 ret = IMultiLanguage2_EnumRfc1766(iML2, LANG_NEUTRAL, &pEnumRfc1766);
1322 ok(ret == S_OK, "IMultiLanguage2_EnumRfc1766 error %08x\n", ret);
1323
1324 while (1)
1325 {
1326 ret = IEnumRfc1766_Next(pEnumRfc1766, 1, &info, &n);
1327 if (ret != S_OK) break;
1328
1329#ifdef DUMP_CP_INFO
1330 trace("lcid %04x rfc_name %s locale_name %s\n",
1331 info.lcid, wine_dbgstr_w(info.wszRfc1766), wine_dbgstr_w(info.wszLocaleName));
1332#endif
1333
1334 ok(n == 1, "couldn't fetch 1 RFC1766INFO structure\n");
1335
1336 /* verify the Rfc1766 value */
1337 ret = IMultiLanguage2_GetRfc1766FromLcid(iML2, info.lcid, &rfcstr);
1338 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
1339
1340 /* not an exact 1:1 correspondence between lcid and rfc1766 in the
1341 * mlang database, e.g., nb-no -> 1044 -> no */
1342 ok(strstrW(info.wszRfc1766, rfcstr) != NULL,
1343 "Expected matching locale names\n");
1344
1345 SysFreeString(rfcstr);
1346 }
1347 IEnumRfc1766_Release(pEnumRfc1766);
1348}
1349
1350static void test_GetLcidFromRfc1766(IMultiLanguage2 *iML2)
1351{
1352 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1353 LCID lcid;
1354 HRESULT ret;
1355 DWORD i;
1356
1357 static WCHAR en[] = { 'e','n',0 };
1358 static WCHAR en_them[] = { 'e','n','-','t','h','e','m',0 };
1359 static WCHAR english[] = { 'e','n','g','l','i','s','h',0 };
1360
1361
1362 for(i = 0; i < ARRAY_SIZE(lcid_table); i++) {
1363 lcid = -1;
1364 MultiByteToWideChar(CP_ACP, 0, lcid_table[i].rfc1766, -1, rfc1766W, MAX_RFC1766_NAME);
1365 ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, rfc1766W);
1366
1367 /* IE <6.0 guess 0x412 (ko) from "kok" */
1368 ok((ret == lcid_table[i].hr) ||
1369 broken(lcid_table[i].broken_lcid && (ret == S_FALSE)),
1370 "#%02d: HRESULT 0x%x (expected 0x%x)\n", i, ret, lcid_table[i].hr);
1371
1372 ok((lcid == lcid_table[i].lcid) ||
1373 broken(lcid == lcid_table[i].broken_lcid), /* IE <6.0 */
1374 "#%02d: got LCID 0x%x (expected 0x%x)\n", i, lcid, lcid_table[i].lcid);
1375 }
1376
1377
1378 ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, NULL, en);
1379 ok(ret == E_INVALIDARG, "GetLcidFromRfc1766 returned: %08x\n", ret);
1380
1381 ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, NULL);
1382 ok(ret == E_INVALIDARG, "GetLcidFromRfc1766 returned: %08x\n", ret);
1383
1384 ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, en_them);
1385 ok((ret == E_FAIL || ret == S_FALSE), "GetLcidFromRfc1766 returned: %08x\n", ret);
1386 if (ret == S_FALSE)
1387 {
1388 BSTR rfcstr;
1389 static WCHAR en[] = {'e','n',0};
1390
1391 ret = IMultiLanguage2_GetRfc1766FromLcid(iML2, lcid, &rfcstr);
1392 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
1393 ok_w2("Expected \"%s\", got \"%s\"n", en, rfcstr);
1394 }
1395
1396 ret = IMultiLanguage2_GetLcidFromRfc1766(iML2, &lcid, english);
1397 ok((ret == E_FAIL || ret == S_FALSE), "GetLcidFromRfc1766 returned: %08x\n", ret);
1398 if (ret == S_FALSE)
1399 {
1400 BSTR rfcstr;
1401 static WCHAR en[] = {'e','n',0};
1402
1403 ret = IMultiLanguage2_GetRfc1766FromLcid(iML2, lcid, &rfcstr);
1404 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
1405 ok_w2("Expected \"%s\", got \"%s\"n", en, rfcstr);
1406 }
1407
1408}
1409
1410static void test_Rfc1766ToLcid(void)
1411{
1412 LCID lcid;
1413 HRESULT ret;
1414 DWORD i;
1415
1416 for(i = 0; i < ARRAY_SIZE(lcid_table); i++) {
1417 lcid = -1;
1418 ret = pRfc1766ToLcidA(&lcid, lcid_table[i].rfc1766);
1419
1420 /* IE <6.0 guess 0x412 (ko) from "kok" */
1421 ok( (ret == lcid_table[i].hr) ||
1422 broken(lcid_table[i].broken_lcid && (ret == S_FALSE)),
1423 "#%02d: HRESULT 0x%x (expected 0x%x)\n", i, ret, lcid_table[i].hr);
1424
1425 ok( (lcid == lcid_table[i].lcid) ||
1426 broken(lcid == lcid_table[i].broken_lcid), /* IE <6.0 */
1427 "#%02d: got LCID 0x%x (expected 0x%x)\n", i, lcid, lcid_table[i].lcid);
1428 }
1429
1430 ret = pRfc1766ToLcidA(&lcid, NULL);
1431 ok(ret == E_INVALIDARG, "got 0x%08x (expected E_INVALIDARG)\n", ret);
1432
1433 ret = pRfc1766ToLcidA(NULL, "en");
1434 ok(ret == E_INVALIDARG, "got 0x%08x (expected E_INVALIDARG)\n", ret);
1435}
1436
1437static void test_GetNumberOfCodePageInfo(IMultiLanguage2 *iML2)
1438{
1439 HRESULT hr;
1440 UINT value;
1441
1442 value = 0xdeadbeef;
1443 hr = IMultiLanguage2_GetNumberOfCodePageInfo(iML2, &value);
1444 ok( (hr == S_OK) && value,
1445 "got 0x%x with %d (expected S_OK with '!= 0')\n", hr, value);
1446
1447 hr = IMultiLanguage2_GetNumberOfCodePageInfo(iML2, NULL);
1448 ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
1449
1450}
1451
1452static void test_GetRfc1766FromLcid(IMultiLanguage2 *iML2)
1453{
1454 CHAR expected[MAX_RFC1766_NAME];
1455 CHAR buffer[MAX_RFC1766_NAME + 1];
1456 DWORD i;
1457 HRESULT hr;
1458 BSTR rfcstr;
1459
1460 for(i = 0; i < ARRAY_SIZE(lcid_table); i++) {
1461 buffer[0] = '\0';
1462
1463 rfcstr = NULL;
1464 hr = IMultiLanguage2_GetRfc1766FromLcid(iML2, lcid_table[i].lcid, &rfcstr);
1465 ok(hr == lcid_table[i].hr,
1466 "#%02d: HRESULT 0x%x (expected 0x%x)\n", i, hr, lcid_table[i].hr);
1467
1468 if (hr != S_OK)
1469 continue; /* no result-string created */
1470
1471 WideCharToMultiByte(CP_ACP, 0, rfcstr, -1, buffer, sizeof(buffer), NULL, NULL);
1473 lstrlenA(lcid_table[i].rfc1766) + 1, expected, MAX_RFC1766_NAME);
1474
1475 /* IE <6.0 return "x-kok" for LCID 0x457 ("kok") */
1476 ok( (!lstrcmpA(buffer, expected)) ||
1477 broken(!lstrcmpA(buffer, lcid_table[i].broken_rfc)),
1478 "#%02d: got '%s' (expected '%s')\n", i, buffer, expected);
1479
1480 SysFreeString(rfcstr);
1481 }
1482
1483 hr = IMultiLanguage2_GetRfc1766FromLcid(iML2, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), NULL);
1484 ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
1485}
1486
1487static void test_LcidToRfc1766(void)
1488{
1489 CHAR expected[MAX_RFC1766_NAME];
1490 CHAR buffer[MAX_RFC1766_NAME * 2];
1491 HRESULT hr;
1492 DWORD i;
1493
1494 for(i = 0; i < ARRAY_SIZE(lcid_table); i++) {
1495
1496 memset(buffer, '#', sizeof(buffer)-1);
1497 buffer[sizeof(buffer)-1] = '\0';
1498
1499 hr = pLcidToRfc1766A(lcid_table[i].lcid, buffer, MAX_RFC1766_NAME);
1500
1501 /* IE <5.0 does not recognize 0x180c (fr-mc) and 0x457 (kok) */
1502 ok( (hr == lcid_table[i].hr) ||
1503 broken(lcid_table[i].broken_lcid && (hr == E_FAIL)),
1504 "#%02d: HRESULT 0x%x (expected 0x%x)\n", i, hr, lcid_table[i].hr);
1505
1506 if (hr != S_OK)
1507 continue;
1508
1510 lstrlenA(lcid_table[i].rfc1766) + 1, expected, MAX_RFC1766_NAME);
1511
1512 /* IE <6.0 return "x-kok" for LCID 0x457 ("kok") */
1513 /* IE <5.0 return "fr" for LCID 0x180c ("fr-mc") */
1514 ok( (!lstrcmpA(buffer, expected)) ||
1515 broken(!lstrcmpA(buffer, lcid_table[i].broken_rfc)),
1516 "#%02d: got '%s' (expected '%s')\n", i, buffer, expected);
1517
1518 }
1519
1520 memset(buffer, '#', sizeof(buffer)-1);
1521 buffer[sizeof(buffer)-1] = '\0';
1522 hr = pLcidToRfc1766A(-1, buffer, MAX_RFC1766_NAME);
1523 ok(hr == E_FAIL, "got 0x%08x and '%s' (expected E_FAIL)\n", hr, buffer);
1524
1525 hr = pLcidToRfc1766A(LANG_ENGLISH, NULL, MAX_RFC1766_NAME);
1526 ok(hr == E_INVALIDARG, "got 0x%08x (expected E_INVALIDARG)\n", hr);
1527
1528 memset(buffer, '#', sizeof(buffer)-1);
1529 buffer[sizeof(buffer)-1] = '\0';
1530 hr = pLcidToRfc1766A(LANG_ENGLISH, buffer, -1);
1531 ok(hr == E_INVALIDARG, "got 0x%08x and '%s' (expected E_INVALIDARG)\n", hr, buffer);
1532
1533 memset(buffer, '#', sizeof(buffer)-1);
1534 buffer[sizeof(buffer)-1] = '\0';
1535 hr = pLcidToRfc1766A(LANG_ENGLISH, buffer, 0);
1536 ok(hr == E_INVALIDARG, "got 0x%08x and '%s' (expected E_INVALIDARG)\n", hr, buffer);
1537}
1538
1539static void test_GetRfc1766Info(IMultiLanguage2 *iML2)
1540{
1541 WCHAR short_broken_name[MAX_LOCALE_NAME];
1542 CHAR rfc1766A[MAX_RFC1766_NAME + 1];
1543 BYTE buffer[sizeof(RFC1766INFO) + 4];
1544 PRFC1766INFO prfc = (RFC1766INFO *) buffer;
1545 HRESULT ret;
1546 DWORD i;
1547
1548 for(i = 0; i < ARRAY_SIZE(info_table); i++) {
1549 memset(buffer, 'x', sizeof(RFC1766INFO) + 2);
1550 buffer[sizeof(buffer) -1] = 0;
1551 buffer[sizeof(buffer) -2] = 0;
1552
1553 ret = IMultiLanguage2_GetRfc1766Info(iML2, info_table[i].lcid, info_table[i].lang, prfc);
1554 WideCharToMultiByte(CP_ACP, 0, prfc->wszRfc1766, -1, rfc1766A, MAX_RFC1766_NAME, NULL, NULL);
1555 ok(ret == S_OK, "#%02d: got 0x%x (expected S_OK)\n", i, ret);
1556 ok(prfc->lcid == info_table[i].lcid,
1557 "#%02d: got 0x%04x (expected 0x%04x)\n", i, prfc->lcid, info_table[i].lcid);
1558
1559 ok(!lstrcmpA(rfc1766A, info_table[i].rfc1766),
1560 "#%02d: got '%s' (expected '%s')\n", i, rfc1766A, info_table[i].rfc1766);
1561
1562 /* Some IE versions truncate an oversized name one character too short */
1563 if (info_table[i].broken_name) {
1564 lstrcpyW(short_broken_name, info_table[i].broken_name);
1565 short_broken_name[MAX_LOCALE_NAME - 2] = 0;
1566 }
1567
1569 ok( (!lstrcmpW(prfc->wszLocaleName, info_table[i].localename)) ||
1570 (info_table[i].broken_name && (
1571 broken(!lstrcmpW(prfc->wszLocaleName, info_table[i].broken_name)) || /* IE < 6.0 */
1572 broken(!lstrcmpW(prfc->wszLocaleName, short_broken_name)))),
1573 "#%02d: got %s (expected %s)\n", i,
1574 wine_dbgstr_w(prfc->wszLocaleName), wine_dbgstr_w(info_table[i].localename));
1575 }
1576 }
1577
1578 /* SUBLANG_NEUTRAL only allowed for English, Arabic, Chinese */
1579 ret = IMultiLanguage2_GetRfc1766Info(iML2, MAKELANGID(LANG_GERMAN, SUBLANG_NEUTRAL), LANG_ENGLISH, prfc);
1580 ok(ret == E_FAIL, "got 0x%x (expected E_FAIL)\n", ret);
1581
1582 ret = IMultiLanguage2_GetRfc1766Info(iML2, MAKELANGID(LANG_ITALIAN, SUBLANG_NEUTRAL), LANG_ENGLISH, prfc);
1583 ok(ret == E_FAIL, "got 0x%x (expected E_FAIL)\n", ret);
1584
1585 /* NULL not allowed */
1586 ret = IMultiLanguage2_GetRfc1766Info(iML2, 0, LANG_ENGLISH, prfc);
1587 ok(ret == E_FAIL, "got 0x%x (expected E_FAIL)\n", ret);
1588
1589 ret = IMultiLanguage2_GetRfc1766Info(iML2, LANG_ENGLISH, LANG_ENGLISH, NULL);
1590 ok(ret == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", ret);
1591}
1592
1593static void test_IMultiLanguage2_ConvertStringFromUnicode(IMultiLanguage2 *iML2)
1594{
1596 CHAR invariate[MAX_PATH];
1597 UINT srcsz, destsz;
1598 HRESULT hr;
1599
1600 static WCHAR src[] = {'a','b','c',0};
1601
1602 memset(invariate, 'x', sizeof(invariate));
1603
1604 /* pSrcStr NULL */
1605 memset(dest, 'x', sizeof(dest));
1606 srcsz = lstrlenW(src) + 1;
1607 destsz = sizeof(dest);
1608 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, NULL,
1609 &srcsz, dest, &destsz);
1610 ok(hr == S_OK || hr == E_FAIL,"expected S_OK or E_FAIL, got %08x\n",hr);
1611 if (hr == S_OK)
1612 {
1613 ok(srcsz == lstrlenW(src) + 1,
1614 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1615 }
1616 else if (hr == E_FAIL)
1617 {
1618 ok(srcsz == 0,
1619 "Expected %u, got %u\n", 0, srcsz);
1620 }
1621
1622 ok(!memcmp(dest, invariate, sizeof(dest)),
1623 "Expected dest to be unchanged, got %s\n", dest);
1624 ok(destsz == 0, "Expected 0, got %u\n", destsz);
1625
1626 /* pcSrcSize NULL */
1627 memset(dest, 'x', sizeof(dest));
1628 destsz = sizeof(dest);
1629 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1630 NULL, dest, &destsz);
1631 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1632 ok(!strncmp(dest, "abc", 3),
1633 "Expected first three chars to be \"abc\"\n");
1634 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1635 "Expected rest of dest to be unchanged, got %s\n", dest);
1636 ok(destsz == lstrlenW(src),
1637 "Expected %u, got %u\n", lstrlenW(src), destsz);
1638
1639 /* both pSrcStr and pcSrcSize NULL */
1640 memset(dest, 'x', sizeof(dest));
1641 destsz = sizeof(dest);
1642 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, NULL,
1643 NULL, dest, &destsz);
1644 ok(hr == S_OK || hr == E_FAIL, "Expected S_OK or E_FAIL, got %08x\n", hr);
1645 ok(!memcmp(dest, invariate, sizeof(dest)),
1646 "Expected dest to be unchanged, got %s\n", dest);
1647 ok(destsz == 0, "Expected 0, got %u\n", destsz);
1648
1649 /* pDstStr NULL */
1650 memset(dest, 'x', sizeof(dest));
1651 srcsz = lstrlenW(src) + 1;
1652 destsz = sizeof(dest);
1653 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1654 &srcsz, NULL, &destsz);
1655 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1656 ok(srcsz == lstrlenW(src) + 1,
1657 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1658 ok(destsz == lstrlenW(src) + 1,
1659 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1660
1661 /* pcDstSize NULL */
1662 memset(dest, 'x', sizeof(dest));
1663 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1664 &srcsz, dest, NULL);
1665 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1666 ok(srcsz == lstrlenW(src) + 1,
1667 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1668 ok(!memcmp(dest, invariate, sizeof(dest)),
1669 "Expected dest to be unchanged, got %s\n", dest);
1670
1671 /* pcSrcSize is 0 */
1672 memset(dest, 'x', sizeof(dest));
1673 srcsz = 0;
1674 destsz = sizeof(dest);
1675 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1676 &srcsz, dest, &destsz);
1677 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1678 ok(srcsz == 0, "Expected 0, got %u\n", srcsz);
1679 ok(!memcmp(dest, invariate, sizeof(dest)),
1680 "Expected dest to be unchanged, got %s\n", dest);
1681 ok(destsz == 0, "Expected 0, got %u\n", destsz);
1682
1683 /* pcSrcSize does not include NULL terminator */
1684 memset(dest, 'x', sizeof(dest));
1685 srcsz = lstrlenW(src);
1686 destsz = sizeof(dest);
1687 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1688 &srcsz, dest, &destsz);
1689 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1690 ok(srcsz == lstrlenW(src),
1691 "Expected %u, got %u\n", lstrlenW(src), srcsz);
1692 ok(!strncmp(dest, "abc", 3), "Expected first three chars to be \"abc\"\n");
1693 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1694 "Expected rest of dest to be unchanged, got %s\n", dest);
1695 ok(destsz == lstrlenW(src),
1696 "Expected %u, got %u\n", lstrlenW(src), destsz);
1697
1698 /* pcSrcSize includes NULL terminator */
1699 memset(dest, 'x', sizeof(dest));
1700 srcsz = lstrlenW(src) + 1;
1701 destsz = sizeof(dest);
1702 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1703 &srcsz, dest, &destsz);
1704 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1705 ok(srcsz == lstrlenW(src) + 1, "Expected 3, got %u\n", srcsz);
1706 ok(!lstrcmpA(dest, "abc"), "Expected \"abc\", got \"%s\"\n", dest);
1707 ok(destsz == lstrlenW(src) + 1,
1708 "Expected %u, got %u\n", lstrlenW(src) + 1, destsz);
1709
1710 /* pcSrcSize is -1 */
1711 memset(dest, 'x', sizeof(dest));
1712 srcsz = -1;
1713 destsz = sizeof(dest);
1714 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1715 &srcsz, dest, &destsz);
1716 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1717 ok(srcsz == lstrlenW(src),
1718 "Expected %u, got %u\n", lstrlenW(src), srcsz);
1719 ok(!strncmp(dest, "abc", 3), "Expected first three chars to be \"abc\"\n");
1720 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1721 "Expected rest of dest to be unchanged, got %s\n", dest);
1722 ok(destsz == lstrlenW(src),
1723 "Expected %u, got %u\n", lstrlenW(src), destsz);
1724
1725 /* pcDstSize is 0 */
1726 memset(dest, 'x', sizeof(dest));
1727 srcsz = lstrlenW(src) + 1;
1728 destsz = 0;
1729 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1730 &srcsz, dest, &destsz);
1731 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1732 ok(srcsz == lstrlenW(src) + 1,
1733 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1734 ok(!memcmp(dest, invariate, sizeof(dest)),
1735 "Expected dest to be unchanged, got %s\n", dest);
1736 ok(destsz == lstrlenW(src) + 1,
1737 "Expected %u, got %u\n", lstrlenW(src) + 1, destsz);
1738
1739 /* pcDstSize is not large enough */
1740 memset(dest, 'x', sizeof(dest));
1741 srcsz = lstrlenW(src) + 1;
1742 destsz = lstrlenW(src);
1743 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1744 &srcsz, dest, &destsz);
1745 ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
1746 ok(srcsz == 0, "Expected 0, got %u\n", srcsz);
1747 ok(!strncmp(dest, "abc", 3), "Expected first three chars to be \"abc\"\n");
1748 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1749 "Expected rest of dest to be unchanged, got %s\n", dest);
1750 ok(destsz == 0, "Expected 0, got %u\n", srcsz);
1751
1752 /* pcDstSize (bytes) does not leave room for NULL terminator */
1753 memset(dest, 'x', sizeof(dest));
1754 srcsz = lstrlenW(src) + 1;
1755 destsz = lstrlenW(src) * sizeof(WCHAR);
1756 hr = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, 1252, src,
1757 &srcsz, dest, &destsz);
1758 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1759 ok(srcsz == lstrlenW(src) + 1,
1760 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1761 ok(!lstrcmpA(dest, "abc"), "Expected \"abc\", got \"%s\"\n", dest);
1762 ok(destsz == lstrlenW(src) + 1,
1763 "Expected %u, got %u\n", lstrlenW(src) + 1, destsz);
1764}
1765
1767{
1769 CHAR invariate[MAX_PATH];
1770 INT srcsz, destsz;
1771 HRESULT hr;
1772
1773 static WCHAR src[] = {'a','b','c',0};
1774
1775 memset(invariate, 'x', sizeof(invariate));
1776
1777 /* lpSrcStr NULL */
1778 memset(dest, 'x', sizeof(dest));
1779 srcsz = lstrlenW(src) + 1;
1780 destsz = sizeof(dest);
1781 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, NULL, &srcsz, dest, &destsz);
1782 ok(hr == S_OK || hr == E_FAIL, "Expected S_OK or E_FAIL, got %08x\n", hr);
1783 if (hr == S_OK)
1784 ok(srcsz == lstrlenW(src) + 1,
1785 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1786 else if (hr == E_FAIL)
1787 ok(srcsz == 0,
1788 "Expected %u, got %u\n", 0, srcsz);
1789 ok(!memcmp(dest, invariate, sizeof(dest)),
1790 "Expected dest to be unchanged, got %s\n", dest);
1791 ok(destsz == 0, "Expected 0, got %u\n", destsz);
1792
1793 /* lpnWideCharCount NULL */
1794 memset(dest, 'x', sizeof(dest));
1795 destsz = sizeof(dest);
1796 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, NULL, dest, &destsz);
1797 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1798 ok(!strncmp(dest, "abc", 3),
1799 "Expected first three chars to be \"abc\"\n");
1800 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1801 "Expected rest of dest to be unchanged, got %s\n", dest);
1802 ok(destsz == lstrlenW(src),
1803 "Expected %u, got %u\n", lstrlenW(src), destsz);
1804
1805 /* both lpSrcStr and lpnWideCharCount NULL */
1806 memset(dest, 'x', sizeof(dest));
1807 destsz = sizeof(dest);
1808 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, NULL, NULL, dest, &destsz);
1809 ok(hr == S_OK || hr == E_FAIL, "Expected S_OK or E_FAIL, got %08x\n", hr);
1810 ok(!memcmp(dest, invariate, sizeof(dest)),
1811 "Expected dest to be unchanged, got %s\n", dest);
1812 ok(destsz == 0, "Expected 0, got %u\n", destsz);
1813
1814 /* lpDstStr NULL */
1815 memset(dest, 'x', sizeof(dest));
1816 srcsz = lstrlenW(src) + 1;
1817 destsz = sizeof(dest);
1818 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, NULL, &destsz);
1819 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1820 ok(srcsz == lstrlenW(src) + 1,
1821 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1822 ok(destsz == lstrlenW(src) + 1,
1823 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1824
1825 /* lpnMultiCharCount NULL */
1826 memset(dest, 'x', sizeof(dest));
1827 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, NULL);
1828 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1829 ok(srcsz == lstrlenW(src) + 1,
1830 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1831 ok(!memcmp(dest, invariate, sizeof(dest)),
1832 "Expected dest to be unchanged, got %s\n", dest);
1833
1834 /* lpnWideCharCount is 0 */
1835 memset(dest, 'x', sizeof(dest));
1836 srcsz = 0;
1837 destsz = sizeof(dest);
1838 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, &destsz);
1839 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1840 ok(srcsz == 0, "Expected 0, got %u\n", srcsz);
1841 ok(!memcmp(dest, invariate, sizeof(dest)),
1842 "Expected dest to be unchanged, got %s\n", dest);
1843 ok(destsz == 0, "Expected 0, got %u\n", destsz);
1844
1845 /* lpnWideCharCount does not include NULL terminator */
1846 memset(dest, 'x', sizeof(dest));
1847 srcsz = lstrlenW(src);
1848 destsz = sizeof(dest);
1849 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, &destsz);
1850 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1851 ok(srcsz == lstrlenW(src),
1852 "Expected %u, got %u\n", lstrlenW(src), srcsz);
1853 ok(!strncmp(dest, "abc", 3), "Expected first three chars to be \"abc\"\n");
1854 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1855 "Expected rest of dest to be unchanged, got %s\n", dest);
1856 ok(destsz == lstrlenW(src),
1857 "Expected %u, got %u\n", lstrlenW(src), destsz);
1858
1859 /* lpnWideCharCount includes NULL terminator */
1860 memset(dest, 'x', sizeof(dest));
1861 srcsz = lstrlenW(src) + 1;
1862 destsz = sizeof(dest);
1863 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, &destsz);
1864 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1865 ok(srcsz == lstrlenW(src) + 1, "Expected 3, got %u\n", srcsz);
1866 ok(!lstrcmpA(dest, "abc"), "Expected \"abc\", got \"%s\"\n", dest);
1867 ok(destsz == lstrlenW(src) + 1,
1868 "Expected %u, got %u\n", lstrlenW(src) + 1, destsz);
1869
1870 /* lpnWideCharCount is -1 */
1871 memset(dest, 'x', sizeof(dest));
1872 srcsz = -1;
1873 destsz = sizeof(dest);
1874 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, &destsz);
1875 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1876 ok(srcsz == lstrlenW(src),
1877 "Expected %u, got %u\n", lstrlenW(src), srcsz);
1878 ok(!strncmp(dest, "abc", 3), "Expected first three chars to be \"abc\"\n");
1879 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1880 "Expected rest of dest to be unchanged, got %s\n", dest);
1881 ok(destsz == lstrlenW(src),
1882 "Expected %u, got %u\n", lstrlenW(src), destsz);
1883
1884 /* lpnMultiCharCount is 0 */
1885 memset(dest, 'x', sizeof(dest));
1886 srcsz = lstrlenW(src) + 1;
1887 destsz = 0;
1888 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, &destsz);
1889 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1890 ok(srcsz == lstrlenW(src) + 1,
1891 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1892 ok(!memcmp(dest, invariate, sizeof(dest)),
1893 "Expected dest to be unchanged, got %s\n", dest);
1894 ok(destsz == lstrlenW(src) + 1,
1895 "Expected %u, got %u\n", lstrlenW(src) + 1, destsz);
1896
1897 /* lpnMultiCharCount is not large enough */
1898 memset(dest, 'x', sizeof(dest));
1899 srcsz = lstrlenW(src) + 1;
1900 destsz = lstrlenW(src);
1901 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, &destsz);
1902 ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
1903 ok(srcsz == 0, "Expected 0, got %u\n", srcsz);
1904 ok(!strncmp(dest, "abc", 3), "Expected first three chars to be \"abc\"\n");
1905 ok(!memcmp(&dest[3], invariate, sizeof(dest) - 3),
1906 "Expected rest of dest to be unchanged, got %s\n", dest);
1907 ok(destsz == 0, "Expected 0, got %u\n", srcsz);
1908
1909 /* lpnMultiCharCount (bytes) does not leave room for NULL terminator */
1910 memset(dest, 'x', sizeof(dest));
1911 srcsz = lstrlenW(src) + 1;
1912 destsz = lstrlenW(src) * sizeof(WCHAR);
1913 hr = pConvertINetUnicodeToMultiByte(NULL, 1252, src, &srcsz, dest, &destsz);
1914 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1915 ok(srcsz == lstrlenW(src) + 1,
1916 "Expected %u, got %u\n", lstrlenW(src) + 1, srcsz);
1917 ok(!lstrcmpA(dest, "abc"), "Expected \"abc\", got \"%s\"\n", dest);
1918 ok(destsz == lstrlenW(src) + 1,
1919 "Expected %u, got %u\n", lstrlenW(src) + 1, destsz);
1920}
1921
1923{
1924 /* Data */
1925 static WCHAR unc_jp[9][12] = {
1926 {9,0x31,0x20,0x3042,0x3044,0x3046,0x3048,0x304a,0x000d,0x000a},
1927 {9,0x31,0x20,0x30a2,0x30a4,0x30a6,0x30a8,0x30aa,0x000d,0x000a},
1928 {9,0x31,0x20,0xff71,0xff72,0xff73,0xff74,0xff75,0x000d,0x000a},
1929 {9,0x31,0x20,0x3041,0x3043,0x3045,0x3047,0x3049,0x000d,0x000a},
1930 {9,0x31,0x20,0x30a1,0x30a3,0x30a5,0x30a7,0x30a9,0x000d,0x000a},
1931 {9,0x31,0x20,0xff67,0xff68,0xff69,0xff6a,0xff6b,0x000d,0x000a},
1932 {9,0x31,0x20,0x300c,0x65e5,0x672c,0x8a9e,0x300d,0x000d,0x000a},
1933 {7,0x31,0x20,0x25c7,0x25c7,0x3012,0x000d,0x000a},
1934 {11,0x31,0x20,0x203b,0x3010,0x0074,0x0065,0x0073,0x0074,0x3011,0x000d,0x000a}
1935 };
1936 static CHAR jis_jp[9][27] = {
1937 {20,0x31,0x20,0x1b,0x24,0x42,0x24,0x22,0x24,0x24,0x24,0x26,0x24,0x28,
1938 0x24,0x2a,0x1b,0x28,0x42,0x0d,0x0a},
1939 {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x22,0x25,0x24,0x25,0x26,0x25,0x28,
1940 0x25,0x2a,0x1b,0x28,0x42,0x0d,0x0a},
1941 {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x22,0x25,0x24,0x25,0x26,0x25,0x28,
1942 0x25,0x2a,0x1b,0x28,0x42,0x0d,0x0a},
1943 {20,0x31,0x20,0x1b,0x24,0x42,0x24,0x21,0x24,0x23,0x24,0x25,0x24,0x27,
1944 0x24,0x29,0x1b,0x28,0x42,0x0d,0x0a},
1945 {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x21,0x25,0x23,0x25,0x25,0x25,0x27,
1946 0x25,0x29,0x1b,0x28,0x42,0x0d,0x0a},
1947 {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x21,0x25,0x23,0x25,0x25,0x25,0x27,
1948 0x25,0x29,0x1b,0x28,0x42,0x0d,0x0a},
1949 {20,0x31,0x20,0x1b,0x24,0x42,0x21,0x56,0x46,0x7c,0x4b,0x5c,0x38,0x6c,
1950 0x21,0x57,0x1b,0x28,0x42,0x0d,0x0a},
1951 {16,0x31,0x20,0x1b,0x24,0x42,0x21,0x7e,0x21,0x7e,0x22,0x29,0x1b,0x28,
1952 0x42,0x0d,0x0a},
1953 {26,0x31,0x20,0x1b,0x24,0x42,0x22,0x28,0x21,0x5a,0x1b,0x28,0x42,0x74,
1954 0x65,0x73,0x74,0x1b,0x24,0x42,0x21,0x5b,0x1b,0x28,0x42,0x0d,0x0a}
1955 };
1956 static CHAR sjis_jp[9][15] = {
1957 {14,0x31,0x20,0x82,0xa0,0x82,0xa2,0x82,0xa4,0x82,0xa6,0x82,0xa8,0x0d,0x0a},
1958 {14,0x31,0x20,0x83,0x41,0x83,0x43,0x83,0x45,0x83,0x47,0x83,0x49,0x0d,0x0a},
1959 {9,0x31,0x20,0xb1,0xb2,0xb3,0xb4,0xb5,0x0d,0x0a},
1960 {14,0x31,0x20,0x82,0x9f,0x82,0xa1,0x82,0xa3,0x82,0xa5,0x82,0xa7,0x0d,0x0a},
1961 {14,0x31,0x20,0x83,0x40,0x83,0x42,0x83,0x44,0x83,0x46,0x83,0x48,0x0d,0x0a},
1962 {9,0x31,0x20,0xa7,0xa8,0xa9,0xaa,0xab,0x0d,0x0a},
1963 {14,0x31,0x20,0x81,0x75,0x93,0xfa,0x96,0x7b,0x8c,0xea,0x81,0x76,0x0d,0x0a},
1964 {10,0x31,0x20,0x81,0x9e,0x81,0x9e,0x81,0xa7,0x0d,0x0a},
1965 {14,0x31,0x20,0x81,0xa6,0x81,0x79,0x74,0x65,0x73,0x74,0x81,0x7a,0x0d,0x0a}
1966 };
1967 static CHAR euc_jp[9][15] = {
1968 {14,0x31,0x20,0xa4,0xa2,0xa4,0xa4,0xa4,0xa6,0xa4,0xa8,0xa4,0xaa,0x0d,0x0a},
1969 {14,0x31,0x20,0xa5,0xa2,0xa5,0xa4,0xa5,0xa6,0xa5,0xa8,0xa5,0xaa,0x0d,0x0a},
1970 {14,0x31,0x20,0x8e,0xb1,0x8e,0xb2,0x8e,0xb3,0x8e,0xb4,0x8e,0xb5,0x0d,0x0a},
1971 {14,0x31,0x20,0xa4,0xa1,0xa4,0xa3,0xa4,0xa5,0xa4,0xa7,0xa4,0xa9,0x0d,0x0a},
1972 {14,0x31,0x20,0xa5,0xa1,0xa5,0xa3,0xa5,0xa5,0xa5,0xa7,0xa5,0xa9,0x0d,0x0a},
1973 {14,0x31,0x20,0x8e,0xa7,0x8e,0xa8,0x8e,0xa9,0x8e,0xaa,0x8e,0xab,0x0d,0x0a},
1974 {14,0x31,0x20,0xa1,0xd6,0xc6,0xfc,0xcb,0xdc,0xb8,0xec,0xa1,0xd7,0x0d,0x0a},
1975 {10,0x31,0x20,0xa1,0xfe,0xa1,0xfe,0xa2,0xa9,0x0d,0x0a},
1976 {14,0x31,0x20,0xa2,0xa8,0xa1,0xda,0x74,0x65,0x73,0x74,0xa1,0xdb,0x0d,0x0a}
1977 };
1978
1979 INT srcsz, destsz;
1980 INT i;
1981 HRESULT hr;
1982 CHAR output[30];
1983 WCHAR outputW[30];
1984 int outlen;
1985
1986 /* test unc->jis */
1987 for (i = 0; i < 9; i++)
1988 {
1989 int j;
1990 destsz = 30;
1991 outlen = jis_jp[i][0];
1992 srcsz = unc_jp[i][0];
1993 hr = pConvertINetUnicodeToMultiByte(NULL, 50220, &unc_jp[i][1], &srcsz, output, &destsz);
1994 if (hr == S_FALSE)
1995 {
1996 skip("Code page identifier 50220 is not supported\n");
1997 break;
1998 }
1999 ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n", i, hr);
2000 ok(destsz == outlen, "(%i) Expected %i, got %i\n",i,outlen,destsz);
2001 ok(srcsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],srcsz);
2002 ok(memcmp(output,&jis_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i);
2003
2004 /* and back */
2005 srcsz = outlen;
2006 destsz = 30;
2007 hr = pConvertINetMultiByteToUnicode(NULL, 50220, output, &srcsz, outputW,&destsz);
2008
2009 /*
2010 * JIS does not have hankata so it get automatically converted to
2011 * zenkata. this means that strings 1 and 2 are identical as well as
2012 * strings 4 and 5.
2013 */
2014 j = i;
2015 if (i == 2) j = 1;
2016 if (i == 5) j = 4;
2017
2018 ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i, hr);
2019 ok(destsz == unc_jp[j][0],"(%i) Expected %i, got %i\n",i,unc_jp[j][0],destsz);
2020 ok(srcsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,srcsz);
2021 ok(memcmp(outputW,&unc_jp[j][1],destsz)==0,"(%i) Strings do not match\n",i);
2022 }
2023
2024 /* test unc->sjis */
2025 for (i = 0; i < 9; i++)
2026 {
2027 destsz = 30;
2028 outlen = sjis_jp[i][0];
2029 srcsz = unc_jp[i][0];
2030
2031 hr = pConvertINetUnicodeToMultiByte(NULL, 932, &unc_jp[i][1], &srcsz, output, &destsz);
2032 if (hr == S_FALSE)
2033 {
2034 skip("Code page identifier 932 is not supported\n");
2035 break;
2036 }
2037 ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr);
2038 ok(destsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,destsz);
2039 ok(srcsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],srcsz);
2040 ok(memcmp(output,&sjis_jp[i][1],outlen)==0,"(%i) Strings do not match\n",i);
2041
2042 srcsz = outlen;
2043 destsz = 30;
2044 hr = pConvertINetMultiByteToUnicode(NULL, 932, output, &srcsz, outputW,&destsz);
2045
2046 ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n", i, hr);
2047 ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz);
2048 ok(srcsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,srcsz);
2049 ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i);
2050 }
2051
2052 /* test unc->euc */
2053 for (i = 0; i < 9; i++)
2054 {
2055 destsz = 30;
2056 outlen = euc_jp[i][0];
2057 srcsz = unc_jp[i][0];
2058
2059 hr = pConvertINetUnicodeToMultiByte(NULL, 51932, &unc_jp[i][1], &srcsz, output, &destsz);
2060 if (hr == S_FALSE)
2061 {
2062 skip("Code page identifier 51932 is not supported\n");
2063 break;
2064 }
2065 ok(hr == S_OK, "(%i) Expected S_OK, got %08x\n",i,hr);
2066 ok(destsz == outlen, "(%i) Expected %i, got %i\n",i,outlen,destsz);
2067 ok(srcsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz);
2068 ok(memcmp(output,&euc_jp[i][1],outlen)==0,"(%i) Strings do not match\n",i);
2069
2070 srcsz = outlen;
2071 destsz = 30;
2072 hr = pConvertINetMultiByteToUnicode(NULL, 51932, output, &srcsz, outputW,&destsz);
2073
2074 ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr);
2075 ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz);
2076 ok(srcsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,srcsz);
2077 ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i);
2078 }
2079
2080 /* Japanese autodetect */
2081 i = 0;
2082 destsz = 30;
2083 srcsz = jis_jp[i][0];
2084 hr = pConvertINetMultiByteToUnicode(NULL, 50932, &jis_jp[i][1], &srcsz, outputW, &destsz);
2085 if (hr == S_FALSE)
2086 {
2087 skip("Code page identifier 50932 is not supported\n");
2088 return;
2089 }
2090 ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr);
2091 ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz);
2092 ok(srcsz == jis_jp[i][0],"(%i) Expected %i, got %i\n",i,jis_jp[i][0],srcsz);
2093 ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i);
2094
2095 i = 1;
2096 destsz = 30;
2097 srcsz = sjis_jp[i][0];
2098 hr = pConvertINetMultiByteToUnicode(NULL, 50932, &sjis_jp[i][1], &srcsz, outputW, &destsz);
2099 ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr);
2100 ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz);
2101 ok(srcsz == sjis_jp[i][0],"(%i) Expected %i, got %i\n",i,sjis_jp[i][0],srcsz);
2102 ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i);
2103}
2104
2105static void test_GetScriptFontInfo(IMLangFontLink2 *font_link)
2106{
2107 HRESULT hr;
2108 UINT nfonts;
2109 SCRIPTFONTINFO sfi[1];
2110
2111 nfonts = 0;
2112 hr = IMLangFontLink2_GetScriptFontInfo(font_link, sidAsciiLatin, 0, &nfonts, NULL);
2113 ok(hr == S_OK, "GetScriptFontInfo failed %u\n", GetLastError());
2114 ok(nfonts, "unexpected result\n");
2115
2116 nfonts = 0;
2117 hr = IMLangFontLink2_GetScriptFontInfo(font_link, sidAsciiLatin, SCRIPTCONTF_FIXED_FONT, &nfonts, NULL);
2118 ok(hr == S_OK, "GetScriptFontInfo failed %u\n", GetLastError());
2119 ok(nfonts, "unexpected result\n");
2120
2121 nfonts = 0;
2122 hr = IMLangFontLink2_GetScriptFontInfo(font_link, sidAsciiLatin, SCRIPTCONTF_PROPORTIONAL_FONT, &nfonts, NULL);
2123 ok(hr == S_OK, "GetScriptFontInfo failed %u\n", GetLastError());
2124 ok(nfonts, "unexpected result\n");
2125
2126 nfonts = 1;
2127 memset(sfi, 0, sizeof(sfi));
2128 hr = IMLangFontLink2_GetScriptFontInfo(font_link, sidAsciiLatin, SCRIPTCONTF_FIXED_FONT, &nfonts, sfi);
2129 ok(hr == S_OK, "GetScriptFontInfo failed %u\n", GetLastError());
2130 ok(nfonts == 1, "got %u, expected 1\n", nfonts);
2131 ok(sfi[0].scripts != 0, "unexpected result\n");
2132 ok(sfi[0].wszFont[0], "unexpected result\n");
2133
2134 nfonts = 1;
2135 memset(sfi, 0, sizeof(sfi));
2136 hr = IMLangFontLink2_GetScriptFontInfo(font_link, sidAsciiLatin, SCRIPTCONTF_PROPORTIONAL_FONT, &nfonts, sfi);
2137 ok(hr == S_OK, "GetScriptFontInfo failed %u\n", GetLastError());
2138 ok(nfonts == 1, "got %u, expected 1\n", nfonts);
2139 ok(sfi[0].scripts != 0, "unexpected result\n");
2140 ok(sfi[0].wszFont[0], "unexpected result\n");
2141}
2142
2143static void test_CodePageToScriptID(IMLangFontLink2 *font_link)
2144{
2145 HRESULT hr;
2146 UINT i;
2147 SCRIPT_ID sid;
2148 static const struct
2149 {
2150 UINT cp;
2151 SCRIPT_ID sid;
2152 HRESULT hr;
2153 }
2154 cp_sid[] =
2155 {
2156 {874, sidThai},
2157 {932, sidKana},
2158 {936, sidHan},
2159 {949, sidHangul},
2160 {950, sidBopomofo},
2161 {1250, sidAsciiLatin},
2162 {1251, sidCyrillic},
2163 {1252, sidAsciiLatin},
2164 {1253, sidGreek},
2165 {1254, sidAsciiLatin},
2166 {1255, sidHebrew},
2167 {1256, sidArabic},
2168 {1257, sidAsciiLatin},
2169 {1258, sidAsciiLatin},
2170 {CP_UNICODE, 0, E_FAIL}
2171 };
2172
2173 for (i = 0; i < ARRAY_SIZE(cp_sid); i++)
2174 {
2175 hr = IMLangFontLink2_CodePageToScriptID(font_link, cp_sid[i].cp, &sid);
2176 ok(hr == cp_sid[i].hr, "%u CodePageToScriptID failed 0x%08x %u\n", i, hr, GetLastError());
2177 if (SUCCEEDED(hr))
2178 {
2179 ok(sid == cp_sid[i].sid,
2180 "%u got sid %u for codepage %u, expected %u\n", i, sid, cp_sid[i].cp, cp_sid[i].sid);
2181 }
2182 }
2183}
2184
2185static void test_GetFontUnicodeRanges(IMLangFontLink2 *font_link)
2186{
2187 HRESULT hr;
2188 UINT count;
2189 HFONT hfont, old_hfont;
2190 LOGFONTA lf;
2191 HDC hdc;
2192 UNICODERANGE *ur;
2193
2195 memset(&lf, 0, sizeof(lf));
2196 lstrcpyA(lf.lfFaceName, "Arial");
2198 old_hfont = SelectObject(hdc, hfont);
2199
2200 count = 0;
2201 hr = IMLangFontLink2_GetFontUnicodeRanges(font_link, NULL, &count, NULL);
2202 ok(hr == E_FAIL, "expected E_FAIL, got 0x%08x\n", hr);
2203
2204 hr = IMLangFontLink2_GetFontUnicodeRanges(font_link, hdc, NULL, NULL);
2205 ok(hr == E_INVALIDARG, "expected E_FAIL, got 0x%08x\n", hr);
2206
2207 count = 0;
2208 hr = IMLangFontLink2_GetFontUnicodeRanges(font_link, hdc, &count, NULL);
2209 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2210 ok(count, "expected count > 0\n");
2211
2212 ur = HeapAlloc(GetProcessHeap(), 0, sizeof(*ur) * count);
2213
2214 hr = IMLangFontLink2_GetFontUnicodeRanges(font_link, hdc, &count, ur);
2215 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2216
2217 count--;
2218 hr = IMLangFontLink2_GetFontUnicodeRanges(font_link, hdc, &count, ur);
2219 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2220
2221 HeapFree(GetProcessHeap(), 0, ur);
2222
2223 SelectObject(hdc, old_hfont);
2225 DeleteDC(hdc);
2226}
2227
2228static void test_IsCodePageInstallable(IMultiLanguage2 *ml2)
2229{
2230 UINT i;
2231 HRESULT hr;
2232
2233 for (i = 0; i < 0xffff; i++)
2234 {
2235 hr = IMultiLanguage2_IsCodePageInstallable(ml2, i);
2236
2237 /* it would be better to use IMultiLanguage2_ValidateCodePageEx here but that brings
2238 * up an installation dialog on some platforms, even when specifying CPIOD_PEEK.
2239 */
2240 if (IsValidCodePage(i))
2241 ok(hr == S_OK ||
2242 broken(hr == S_FALSE) || /* win2k */
2243 broken(hr == E_INVALIDARG), /* win2k */
2244 "code page %u is valid but not installable 0x%08x\n", i, hr);
2245 }
2246}
2247
2249{
2250 HRESULT ret;
2251 void *unknown;
2252
2254 ok(ret == E_INVALIDARG, "expected E_INVALIDARG got %#x\n", ret);
2255
2256 unknown = (void *)0xdeadbeef;
2258todo_wine {
2259 ok(ret == S_OK, "expected S_OK got %#x\n", ret);
2260 ok(unknown != NULL && unknown != (void *)0xdeadbeef,
2261 "GetGlobalFontLinkObject() returned %p\n", unknown);
2262 }
2263}
2264
2265static void test_IMLangConvertCharset(IMultiLanguage *ml)
2266{
2267 IMLangConvertCharset *convert;
2268 WCHAR strW[] = {'a','b','c','d',0};
2269 UINT cp, src_size, dst_size;
2270 char strA[] = "abcd";
2271 WCHAR buffW[20];
2272 HRESULT hr;
2273
2274 hr = IMultiLanguage_CreateConvertCharset(ml, CP_ACP, CP_UTF8, 0, &convert);
2276 ok(hr == S_FALSE, "expected S_FALSE got 0x%08x\n", hr);
2277
2278 hr = IMLangConvertCharset_GetSourceCodePage(convert, NULL);
2279 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2280
2281 cp = CP_UTF8;
2282 hr = IMLangConvertCharset_GetSourceCodePage(convert, &cp);
2283 ok(hr == S_OK, "expected S_OK got 0x%08x\n", hr);
2284 ok(cp == CP_ACP, "got %d\n", cp);
2285
2286 hr = IMLangConvertCharset_GetDestinationCodePage(convert, NULL);
2287 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2288
2289 cp = CP_ACP;
2290 hr = IMLangConvertCharset_GetDestinationCodePage(convert, &cp);
2291 ok(hr == S_OK, "expected S_OK got 0x%08x\n", hr);
2292 ok(cp == CP_UTF8, "got %d\n", cp);
2293
2294 /* DoConversionToUnicode */
2295 hr = IMLangConvertCharset_Initialize(convert, CP_UTF8, CP_UNICODE, 0);
2296 ok(hr == S_OK, "expected S_OK got 0x%08x\n", hr);
2297
2298 hr = IMLangConvertCharset_DoConversionToUnicode(convert, NULL, NULL, NULL, NULL);
2299 ok(hr == E_FAIL || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
2300
2301 src_size = -1;
2302 dst_size = 20;
2303 buffW[0] = 0;
2304 buffW[4] = 4;
2305 hr = IMLangConvertCharset_DoConversionToUnicode(convert, strA, &src_size, buffW, &dst_size);
2306 ok(hr == S_OK, "got 0x%08x\n", hr);
2307 ok(!memcmp(buffW, strW, 4*sizeof(WCHAR)), "got converted string %s\n", wine_dbgstr_wn(buffW, dst_size));
2308 ok(dst_size == 4, "got %d\n", dst_size);
2309 ok(buffW[4] == 4, "got %d\n", buffW[4]);
2310 ok(src_size == 4, "got %d\n", src_size);
2311
2312 src_size = -1;
2313 dst_size = 0;
2314 buffW[0] = 1;
2315 hr = IMLangConvertCharset_DoConversionToUnicode(convert, strA, &src_size, buffW, &dst_size);
2316 ok(hr == S_OK, "got 0x%08x\n", hr);
2317 ok(buffW[0] == 1, "got %d\n", buffW[0]);
2318 ok(dst_size == 4, "got %d\n", dst_size);
2319 ok(src_size == 4, "got %d\n", src_size);
2320
2321 hr = IMLangConvertCharset_Initialize(convert, CP_UNICODE, CP_UNICODE, 0);
2322 ok(hr == S_OK, "expected S_OK got 0x%08x\n", hr);
2323
2324 IMLangConvertCharset_Release(convert);
2325}
2326
2327static const char stream_data[] = "VCARD2.1test;test";
2329
2331{
2332 ok(FALSE, "unexpected call\n");
2333 return E_NOINTERFACE;
2334}
2335
2337{
2338 ok(FALSE, "unexpected call\n");
2339 return 2;
2340}
2341
2343{
2344 ok(FALSE, "unexpected call\n");
2345 return 1;
2346}
2347
2349{
2350 ULONG size;
2351
2352 if (stream_pos == sizeof(stream_data) - 1)
2353 {
2354 *read = 0;
2355 return S_FALSE;
2356 }
2357 size = min(sizeof(stream_data) - 1 - stream_pos, len);
2359 stream_pos += size;
2360 *read = size;
2361 return S_OK;
2362}
2363
2364static HRESULT WINAPI stream_Write(IStream *iface, const void *buf, ULONG len, ULONG *written)
2365{
2366 ok(FALSE, "unexpected call\n");
2367 return E_NOTIMPL;
2368}
2369
2371 ULARGE_INTEGER *newpos)
2372{
2373 if (origin == STREAM_SEEK_SET)
2374 stream_pos = move.QuadPart;
2375 else if (origin == STREAM_SEEK_CUR)
2376 stream_pos += move.QuadPart;
2377 else if (origin == STREAM_SEEK_END)
2378 stream_pos = sizeof(stream_data) - 1 - move.QuadPart;
2379
2380 if (newpos) newpos->QuadPart = stream_pos;
2381 return S_OK;
2382}
2383
2385{
2386 ok(FALSE, "unexpected call\n");
2387 return E_NOTIMPL;
2388}
2389
2392{
2393 ok(FALSE, "unexpected call\n");
2394 return E_NOTIMPL;
2395}
2396
2398{
2399 ok(FALSE, "unexpected call\n");
2400 return E_NOTIMPL;
2401}
2402
2404{
2405 ok(FALSE, "unexpected call\n");
2406 return E_NOTIMPL;
2407}
2408
2410 ULARGE_INTEGER len, DWORD locktype)
2411{
2412 ok(FALSE, "unexpected call\n");
2413 return E_NOTIMPL;
2414}
2415
2417 ULARGE_INTEGER len, DWORD locktype)
2418{
2419 ok(FALSE, "unexpected call\n");
2420 return E_NOTIMPL;
2421}
2422
2423static HRESULT WINAPI stream_Stat(IStream *iface, STATSTG *stg, DWORD flag)
2424{
2425 ok(FALSE, "unexpected call\n");
2426 return E_NOTIMPL;
2427}
2428
2430{
2431 ok(FALSE, "unexpected call\n");
2432 return E_NOTIMPL;
2433}
2434
2435static const IStreamVtbl stream_vtbl =
2436{
2451};
2452
2454
2455static void test_DetectOutboundCodePageInIStream(IMultiLanguage3 *ml)
2456{
2457 HRESULT hr;
2458 UINT nb_detected, detected[4];
2459 UINT preferred[] = {1250,1251,1252,65001};
2460 UINT preferred2[] = {1250,1251,1252};
2461
2462 nb_detected = 0;
2463 memset(detected, 0, sizeof(detected));
2464 hr = IMultiLanguage3_DetectOutboundCodePageInIStream(ml,
2465 MLDETECTF_PRESERVE_ORDER, &test_stream, preferred,
2466 ARRAY_SIZE(preferred), detected, &nb_detected, NULL);
2467 ok(hr == E_INVALIDARG, "got %08x\n", hr);
2468
2469 nb_detected = 1;
2470 memset(detected, 0, sizeof(detected));
2471 hr = IMultiLanguage3_DetectOutboundCodePageInIStream(ml,
2472 MLDETECTF_PRESERVE_ORDER, &test_stream, preferred,
2473 ARRAY_SIZE(preferred), NULL, &nb_detected, NULL);
2474 ok(hr == E_INVALIDARG, "got %08x\n", hr);
2475
2476 nb_detected = 1;
2477 memset(detected, 0, sizeof(detected));
2478 hr = IMultiLanguage3_DetectOutboundCodePageInIStream(ml,
2479 MLDETECTF_PRESERVE_ORDER, &test_stream, preferred,
2480 ARRAY_SIZE(preferred), detected, &nb_detected, NULL);
2481 ok(hr == S_OK, "got %08x\n", hr);
2482 ok(nb_detected == 1, "got %u\n", nb_detected);
2483 ok(detected[0] == 65001, "got %u\n", detected[0]);
2484
2485 nb_detected = 2;
2486 memset(detected, 0, sizeof(detected));
2487 hr = IMultiLanguage3_DetectOutboundCodePageInIStream(ml,
2488 MLDETECTF_PRESERVE_ORDER, &test_stream, preferred,
2489 ARRAY_SIZE(preferred), detected, &nb_detected, NULL);
2490 ok(hr == S_OK, "got %08x\n", hr);
2491 todo_wine ok(nb_detected == 2, "got %u\n", nb_detected);
2492 ok(detected[0] == 65001, "got %u\n", detected[0]);
2493 todo_wine ok(detected[1] == 65000, "got %u\n", detected[1]);
2494
2495 nb_detected = 3;
2496 memset(detected, 0, sizeof(detected));
2497 hr = IMultiLanguage3_DetectOutboundCodePageInIStream(ml,
2498 MLDETECTF_PRESERVE_ORDER, &test_stream, preferred,
2499 ARRAY_SIZE(preferred), detected, &nb_detected, NULL);
2500 ok(hr == S_OK, "got %08x\n", hr);
2501 todo_wine ok(nb_detected == 3, "got %u\n", nb_detected);
2502 ok(detected[0] == 65001, "got %u\n", detected[0]);
2503 todo_wine ok(detected[1] == 65000, "got %u\n", detected[1]);
2504 todo_wine ok(detected[2] == 1200, "got %u\n", detected[2]);
2505
2506 nb_detected = 4;
2507 memset(detected, 0, sizeof(detected));
2508 hr = IMultiLanguage3_DetectOutboundCodePageInIStream(ml,
2509 MLDETECTF_PRESERVE_ORDER, &test_stream, preferred,
2510 ARRAY_SIZE(preferred), detected, &nb_detected, NULL);
2511 ok(hr == S_OK, "got %08x\n", hr);
2512 todo_wine ok(nb_detected == 3, "got %u\n", nb_detected);
2513 ok(detected[0] == 65001, "got %u\n", detected[0]);
2514 todo_wine ok(detected[1] == 65000, "got %u\n", detected[1]);
2515 todo_wine ok(detected[2] == 1200, "got %u\n", detected[2]);
2516 ok(detected[3] == 0, "got %u\n", detected[3]);
2517
2518 nb_detected = 3;
2519 memset(detected, 0, sizeof(detected));
2520 hr = IMultiLanguage3_DetectOutboundCodePageInIStream(ml,
2521 MLDETECTF_PRESERVE_ORDER, &test_stream, preferred2,
2522 ARRAY_SIZE(preferred2), detected, &nb_detected, NULL);
2523 ok(hr == S_OK, "got %08x\n", hr);
2524 todo_wine ok(nb_detected == 3, "got %u\n", nb_detected);
2525 ok(detected[0] == 65001, "got %u\n", detected[0]);
2526 todo_wine ok(detected[1] == 65000, "got %u\n", detected[1]);
2527 todo_wine ok(detected[2] == 1200, "got %u\n", detected[2]);
2528}
2529
2530static void test_GetCodePageInfo(IMultiLanguage2 *iML2)
2531{
2532 static const DWORD VALID_MASK = (DWORD)(~(MIMECONTF_VALID_NLS | MIMECONTF_VALID));
2533
2534 const struct cpinfo_test_data *test_data = NULL;
2535 UINT test_data_num;
2536 MIMECPINFO cpinfo_cmp;
2537 MIMECPINFO cpinfo;
2538 UINT i;
2539 HRESULT ret;
2540
2542 test_data_num = ARRAY_SIZE(iml2_cpinfo_data);
2543 for (i = 0; i < test_data_num; i++)
2544 {
2545 ret = IMultiLanguage2_GetCodePageInfo(iML2, test_data[i].cpinfo.uiCodePage, LANG_NEUTRAL, &cpinfo);
2547 ok(ret == S_OK, "%d: IMultiLanguage2_GetCodePageInfo failed: 0x%08x.\n", i, ret);
2548
2549 if (ret == S_OK)
2550 {
2551 cpinfo_cmp = test_data[i].cpinfo;
2553 ok((cpinfo.dwFlags == cpinfo_cmp.dwFlags ) ||
2554 /* some code pages are not installed on the Wine Test Bot */
2555 ((cpinfo.dwFlags & VALID_MASK) == (cpinfo_cmp.dwFlags & VALID_MASK)),
2556 "%d: got wrong dwFlags expected 0x%x return 0x%x.\n",
2557 i, cpinfo_cmp.dwFlags, cpinfo.dwFlags);
2558 ok(cpinfo.uiCodePage == cpinfo_cmp.uiCodePage,
2559 "%d: got wrong uiCodePage expected %u return %u.\n",
2560 i, cpinfo_cmp.uiCodePage, cpinfo.uiCodePage);
2562 ok(cpinfo.uiFamilyCodePage == cpinfo_cmp.uiFamilyCodePage,
2563 "%d: got wrong uiFamilyCodePage expected %u return %u.\n",
2564 i, cpinfo_cmp.uiFamilyCodePage, cpinfo.uiFamilyCodePage);
2565
2567 ok(!lstrcmpW(cpinfo.wszWebCharset, cpinfo_cmp.wszWebCharset),
2568 "%d: got wrong wszWebCharset expected %s return %s.\n",
2569 i, wine_dbgstr_w(cpinfo_cmp.wszWebCharset), wine_dbgstr_w(cpinfo.wszWebCharset));
2571 ok(!lstrcmpW(cpinfo.wszHeaderCharset, cpinfo_cmp.wszHeaderCharset),
2572 "%d: got wrong wszHeaderCharset expected %s return %s.\n",
2573 i, wine_dbgstr_w(cpinfo_cmp.wszHeaderCharset), wine_dbgstr_w(cpinfo.wszHeaderCharset));
2575 ok(!lstrcmpW(cpinfo.wszBodyCharset, cpinfo_cmp.wszBodyCharset),
2576 "%d: got wrong wszBodyCharset expected %s return %s.\n",
2577 i, wine_dbgstr_w(cpinfo_cmp.wszBodyCharset), wine_dbgstr_w(cpinfo.wszBodyCharset));
2578
2581 {
2582 /* FIXME: Windows returns description and font name in system's language */
2583 skip("Non-English locale\n");
2584 }
2585 else
2586 {
2588 ok(!lstrcmpW(cpinfo.wszDescription, cpinfo_cmp.wszDescription),
2589 "%d: got wrong wszDescription expected %s return %s.\n",
2590 i, wine_dbgstr_w(cpinfo_cmp.wszDescription), wine_dbgstr_w(cpinfo.wszDescription));
2592 ok(!lstrcmpW(cpinfo.wszFixedWidthFont, cpinfo_cmp.wszFixedWidthFont),
2593 "%d: got wrong wszFixedWidthFont expected %s return %s.\n",
2594 i, wine_dbgstr_w(cpinfo_cmp.wszFixedWidthFont), wine_dbgstr_w(cpinfo.wszFixedWidthFont));
2596 ok(!lstrcmpW(cpinfo.wszProportionalFont, cpinfo_cmp.wszProportionalFont),
2597 "%d: got wrong wszProportionalFont expected %s return %s.\n",
2598 i, wine_dbgstr_w(cpinfo_cmp.wszProportionalFont), wine_dbgstr_w(cpinfo.wszProportionalFont));
2599 }
2600 }
2601 }
2602}
2603
2604static void test_MapFont(IMLangFontLink *font_link, IMLangFontLink2 *font_link2)
2605{
2606 HFONT old_font = NULL;
2607 HFONT new_font = NULL;
2608 HFONT last_font = NULL;
2609 HFONT font1 = NULL;
2610 HFONT font2 = NULL;
2611 DWORD codepages;
2612 DWORD font_codepages;
2613 HRESULT ret;
2614 HDC hdc;
2615 WCHAR ch;
2616
2617 hdc = GetDC(NULL);
2618 codepages = FS_LATIN1 | FS_LATIN2 | FS_CYRILLIC | FS_GREEK | FS_TURKISH |
2621 old_font = GetCurrentObject(hdc, OBJ_FONT);
2622 ch = 0xfeed;
2623
2624 /* Tests for IMLangFontLink */
2625
2626 ret = IMLangFontLink_ResetFontMapping(font_link);
2627 ok(ret == S_OK, "IMLangFontLink_ResetFontMapping: expected S_OK, got %08x\n", ret);
2628
2629 ret = IMLangFontLink_MapFont(font_link, NULL, 0, NULL, NULL);
2630 ok(ret == E_FAIL, "IMLangFontLink_MapFont: expected E_FAIL, got %08x\n", ret);
2631 ret = IMLangFontLink_MapFont(font_link, NULL, codepages, old_font, &new_font);
2632 ok(ret == E_FAIL, "IMLangFontLink_MapFont: expected E_FAIL, got %08x\n", ret);
2633 ret = IMLangFontLink_MapFont(font_link, hdc, codepages, NULL, &new_font);
2634 ok(ret == E_FAIL, "IMLangFontLink_MapFont: expected E_FAIL, got %08x\n", ret);
2635
2636 ret = IMLangFontLink_MapFont(font_link, hdc, codepages, old_font, NULL);
2637 ok(ret == S_OK, "IMLangFontLink_MapFont: expected S_OK, got %08x\n", ret);
2638 ret = IMLangFontLink_MapFont(font_link, hdc, codepages, old_font, &new_font);
2639 ok(ret == S_OK && new_font != NULL, "IMLangFontLink_MapFont: expected S_OK/!NULL, got %08x/%p\n", ret, new_font);
2640 last_font = new_font;
2641 ret = IMLangFontLink_MapFont(font_link, hdc, codepages, old_font, &new_font);
2642 ok(ret == S_OK && new_font == last_font, "IMLangFontLink_MapFont: expected S_OK/%p, got %08x/%p\n", last_font, ret, new_font);
2643
2644 ret = IMLangFontLink_ReleaseFont(font_link, NULL);
2645 ok(ret == E_FAIL, "IMLangFontLink_ReleaseFont: expected E_FAIL, got %08x\n", ret);
2646 ret = IMLangFontLink_ReleaseFont(font_link, new_font);
2647 ok(ret == S_OK, "IMLangFontLink_ReleaseFont: expected S_OK, got %08x\n", ret);
2648 ret = IMLangFontLink_ResetFontMapping(font_link);
2649 ok(ret == S_OK, "IMLangFontLink_ResetFontMapping: expected S_OK, got %08x\n", ret);
2650
2651 /* Tests for IMLangFontLink2 */
2652
2653 ret = IMLangFontLink2_ResetFontMapping(font_link2);
2654 ok(ret == S_OK, "IMLangFontLink2_ResetFontMapping: expected S_OK, got %08x\n", ret);
2655
2656 ret = IMLangFontLink2_MapFont(font_link2, NULL, 0, 0, NULL);
2657 ok(ret == E_FAIL, "IMLangFontLink2_MapFont: expected E_FAIL, got %08x\n", ret);
2658 ret = IMLangFontLink2_MapFont(font_link2, NULL, codepages, ch, &new_font);
2659 ok(ret == E_FAIL, "IMLangFontLink2_MapFont: expected E_FAIL, got %08x\n", ret);
2660 ret = IMLangFontLink2_MapFont(font_link2, hdc, 0, 0, NULL);
2661 ok(ret == E_INVALIDARG, "IMLangFontLink2_MapFont: expected E_INVALIDARG, got %08x\n", ret);
2662 ret = IMLangFontLink2_MapFont(font_link2, hdc, 0, ch, NULL);
2663 ok(ret == E_INVALIDARG, "IMLangFontLink2_MapFont: expected E_INVALIDARG, got %08x\n", ret);
2664
2665 ret = IMLangFontLink2_MapFont(font_link2, hdc, 0, ch, &new_font);
2666 todo_wine
2667 ok(ret == S_OK || broken(ret == E_FAIL), /* got E_FAIL on winxp and win2k */
2668 "IMLangFontLink2_MapFont: expected S_OK || E_FAIL, got %08x\n", ret);
2669 ret = IMLangFontLink2_MapFont(font_link2, hdc, codepages, 0, NULL);
2670 ok(ret == S_OK, "IMLangFontLink2_MapFont: expected S_OK, got %08x\n", ret);
2671 ret = IMLangFontLink2_MapFont(font_link2, hdc, codepages, 0, &new_font);
2672 ok(ret == S_OK && new_font != NULL, "IMLangFontLink2_MapFont: expected S_OK/!NULL, got %08x/%p\n", ret, new_font);
2673 last_font = new_font;
2674 ret = IMLangFontLink2_MapFont(font_link2, hdc, codepages, 0, &new_font);
2675 ok(ret == S_OK && new_font == last_font, "IMLangFontLink2_MapFont: expected S_OK/%p, got %08x/%p\n", last_font, ret, new_font);
2676
2677 ret = IMLangFontLink2_ReleaseFont(font_link2, NULL);
2678 ok(ret == E_FAIL, "IMLangFontLink2_ReleaseFont: expected E_FAIL, got %08x\n", ret);
2679 ret = IMLangFontLink2_ReleaseFont(font_link2, new_font);
2680 ok(ret == S_OK, "IMLangFontLink2_ReleaseFont: expected S_OK, got %08x\n", ret);
2681 ret = IMLangFontLink2_ResetFontMapping(font_link2);
2682 ok(ret == S_OK, "IMLangFontLink2_ResetFontMapping: expected S_OK, got %08x\n", ret);
2683
2684 /* Show that the font cache is global */
2685 ret = IMLangFontLink_MapFont(font_link, hdc, codepages, old_font, &font1);
2686 ok(ret == S_OK, "MapFont() failed, hr %#x.\n", ret);
2687 ret = IMLangFontLink2_MapFont(font_link2, hdc, codepages, 0, &font2);
2688 ok(ret == S_OK, "MapFont() failed, hr %#x.\n", ret);
2689 ok(font1 != NULL && font2 != NULL, "expected !NULL/!NULL, got %p/%p\n", font1, font2);
2690 ok(font1 == font2, "expected equal, got not equal\n");
2691
2692 IMLangFontLink_GetFontCodePages(font_link, hdc, font1, &font_codepages);
2693 ok((codepages & (~font_codepages)) != 0 && (codepages & font_codepages) != 0,
2694 "code pages of font is incorrect\n");
2695
2696 IMLangFontLink_ResetFontMapping(font_link);
2697 IMLangFontLink2_ResetFontMapping(font_link2);
2698 ReleaseDC(NULL, hdc);
2699}
2700
2702{
2703 IMultiLanguage *iML = NULL;
2704 IMultiLanguage2 *iML2 = NULL;
2705 IMultiLanguage3 *iML3 = NULL;
2706 IMLangFontLink *iMLFL = NULL;
2707 IMLangFontLink2 *iMLFL2 = NULL;
2708 HRESULT ret;
2709
2710 if (!init_function_ptrs())
2711 return;
2712
2716
2719
2721
2722 trace("IMultiLanguage\n");
2723 ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
2724 &IID_IMultiLanguage, (void **)&iML);
2725 if (ret != S_OK || !iML) return;
2726
2727 test_GetNumberOfCodePageInfo((IMultiLanguage2 *)iML);
2730 IMultiLanguage_Release(iML);
2731
2732
2733 /* IMultiLanguage2 (IE5.0 and above) */
2734 trace("IMultiLanguage2\n");
2735 ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
2736 &IID_IMultiLanguage2, (void **)&iML2);
2737 if (ret != S_OK || !iML2) return;
2738
2739 test_rfc1766(iML2);
2742 test_GetRfc1766Info(iML2);
2745
2746 test_EnumCodePages(iML2, 0);
2747 test_EnumCodePages(iML2, MIMECONTF_MIME_LATEST);
2748 test_EnumCodePages(iML2, MIMECONTF_BROWSER);
2749 test_EnumCodePages(iML2, MIMECONTF_MINIMAL);
2750 test_EnumCodePages(iML2, MIMECONTF_VALID);
2751 /* FIXME: why MIMECONTF_MIME_REGISTRY returns 0 of supported codepages? */
2752 /*test_EnumCodePages(iML2, MIMECONTF_MIME_REGISTRY);*/
2753
2754 test_EnumScripts(iML2, 0);
2755 test_EnumScripts(iML2, SCRIPTCONTF_SCRIPT_USER);
2756 test_EnumScripts(iML2, SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM);
2757
2758 ret = IMultiLanguage2_IsConvertible(iML2, CP_UTF8, CP_UNICODE);
2759 ok(ret == S_OK, "IMultiLanguage2_IsConvertible(CP_UTF8 -> CP_UNICODE) = %08x\n", ret);
2760 ret = IMultiLanguage2_IsConvertible(iML2, CP_UNICODE, CP_UTF8);
2761 ok(ret == S_OK, "IMultiLanguage2_IsConvertible(CP_UNICODE -> CP_UTF8) = %08x\n", ret);
2762
2765
2767
2768 IMultiLanguage2_Release(iML2);
2769
2770
2771 /* IMLangFontLink */
2772 ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
2773 &IID_IMLangFontLink, (void **)&iMLFL);
2774 if (ret != S_OK || !iMLFL) return;
2775
2776 IMLangFontLink_Test(iMLFL);
2777
2778 /* IMLangFontLink2 */
2779 ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
2780 &IID_IMLangFontLink2, (void **)&iMLFL2);
2781 if (ret != S_OK || !iMLFL2) return;
2782
2783 test_GetScriptFontInfo(iMLFL2);
2786 test_MapFont(iMLFL, iMLFL2);
2787
2788 IMLangFontLink_Release(iMLFL);
2789 IMLangFontLink2_Release(iMLFL2);
2790
2791 trace("IMultiLanguage3\n");
2792 ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
2793 &IID_IMultiLanguage3, (void **)&iML3);
2794 if (ret == S_OK)
2795 {
2797 IMultiLanguage3_Release(iML3);
2798 }
2799
2801}
static HFONT hfont
#define broken(x)
Definition: _sntprintf.h:21
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define read
Definition: acwin.h:96
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:33
FT_UInt sid
Definition: cffcmap.c:139
CFF_Charset charset
Definition: cffcmap.c:138
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static WCHAR unknown[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1605
const char * wine_dbgstr_wn(const WCHAR *str, int n)
Definition: compat.c:367
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define GetProcAddress(x, y)
Definition: compat.h:753
#define HeapAlloc
Definition: compat.h:733
OLECHAR * BSTR
Definition: compat.h:2293
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define lstrlenW
Definition: compat.h:750
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2800
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen, LPSTR dst, INT dstlen)
Definition: locale.c:3830
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2078
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4242
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4194
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4261
LCID WINAPI GetSystemDefaultLCID(void)
Definition: locale.c:1229
HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
Definition: mlang.c:3999
static const WCHAR asciiW[]
Definition: mlang.c:395
static IMultiLanguage2 * mlang
Definition: main.c:43
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
#define CP_UNICODE
Definition: stg_prop.c:74
int en
Definition: doserrmap.h:8
static const WCHAR stringW[]
Definition: engine.c:38
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
size_t total
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define WC_DEFAULTCHAR
Definition: unicode.h:45
#define WC_COMPOSITECHECK
Definition: unicode.h:43
#define WC_NO_BEST_FIT_CHARS
Definition: unicode.h:46
static const WCHAR autoW[]
Definition: htmlbody.c:590
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
voidpf uLong int origin
Definition: ioapi.h:144
#define wine_dbgstr_w
Definition: kernel32.h:34
USHORT LANGID
Definition: mui.h:9
if(dx< 0)
Definition: linetemp.h:194
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
POINT cp
Definition: magnifier.c:59
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:92
BOOL todo
Definition: filedlg.c:313
BOOL expected
Definition: store.c:2063
static void test_GetFontUnicodeRanges(void)
Definition: font.c:2741
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static HRESULT WINAPI stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype)
Definition: mlang.c:2409
static LPINT
Definition: mlang.c:47
static void test_LcidToRfc1766(void)
Definition: mlang.c:1487
static const WCHAR de_engb2[]
Definition: mlang.c:122
static LPSTR
Definition: mlang.c:49
static HRESULT WINAPI stream_Stat(IStream *iface, STATSTG *stg, DWORD flag)
Definition: mlang.c:2423
static const WCHAR en_engb[]
Definition: mlang.c:140
static void test_GetLcidFromRfc1766(IMultiLanguage2 *iML2)
Definition: mlang.c:1350
static const info_table_entry info_table[]
Definition: mlang.c:169
static void test_MapFont(IMLangFontLink *font_link, IMLangFontLink2 *font_link2)
Definition: mlang.c:2604
static HRESULT check_convertible(IMultiLanguage2 *iML2, UINT from, UINT to)
Definition: mlang.c:741
static void test_CodePageToScriptID(IMLangFontLink2 *font_link)
Definition: mlang.c:2143
static void test_JapaneseConversion(void)
Definition: mlang.c:1922
static ULONG WINAPI stream_AddRef(IStream *iface)
Definition: mlang.c:2336
static void test_GetGlobalFontLinkObject(void)
Definition: mlang.c:2248
static const WCHAR de_en[]
Definition: mlang.c:117
static void IMLangFontLink_Test(IMLangFontLink *iMLFL)
Definition: mlang.c:1164
static const WCHAR en_en[]
Definition: mlang.c:137
static const WCHAR de_engb[]
Definition: mlang.c:120
static const WCHAR en_de[]
Definition: mlang.c:144
static LPCPINFOEXA
Definition: mlang.c:45
static const WCHAR de_enca[]
Definition: mlang.c:118
static HRESULT WINAPI stream_Clone(IStream *iface, IStream **stream)
Definition: mlang.c:2429
static void test_rfc1766(IMultiLanguage2 *iML2)
Definition: mlang.c:1313
static const WCHAR fr_enca[]
Definition: mlang.c:152
static HRESULT WINAPI stream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER len, ULARGE_INTEGER *read, ULARGE_INTEGER *written)
Definition: mlang.c:2390
static void test_GetRfc1766FromLcid(IMultiLanguage2 *iML2)
Definition: mlang.c:1452
static INT
Definition: mlang.c:51
static const WCHAR de_deat[]
Definition: mlang.c:132
static const WCHAR fr_de2[]
Definition: mlang.c:162
static const struct cpinfo_test_data iml2_cpinfo_data[]
Definition: mlang.c:247
static void test_IMultiLanguage2_ConvertStringFromUnicode(IMultiLanguage2 *iML2)
Definition: mlang.c:1593
#define ok_w2(format, szString1, szString2)
Definition: mlang.c:559
#define TODO_NAME
Definition: mlang.c:106
static const WCHAR en_enca[]
Definition: mlang.c:138
static const WCHAR fr_enus2[]
Definition: mlang.c:158
static LPWSTR
Definition: mlang.c:47
static const WCHAR fr_enus[]
Definition: mlang.c:156
static const WCHAR fr_deat[]
Definition: mlang.c:164
static void test_EnumScripts(IMultiLanguage2 *iML2, DWORD flags)
Definition: mlang.c:1068
static ULONG stream_pos
Definition: mlang.c:2328
struct info_table_tag info_table_entry
static HRESULT WINAPI stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD locktype)
Definition: mlang.c:2416
static ULONG WINAPI stream_Release(IStream *iface)
Definition: mlang.c:2342
static const WCHAR fr_dech[]
Definition: mlang.c:166
static void test_GetScriptFontInfo(IMLangFontLink2 *font_link)
Definition: mlang.c:2105
static const WCHAR de_enus[]
Definition: mlang.c:125
static void test_GetCodePageInfo(IMultiLanguage2 *iML2)
Definition: mlang.c:2530
static void test_ConvertINetUnicodeToMultiByte(void)
Definition: mlang.c:1766
static void test_multibyte_to_unicode_translations(IMultiLanguage2 *iML2)
Definition: mlang.c:569
static void test_IsCodePageInstallable(IMultiLanguage2 *ml2)
Definition: mlang.c:2228
static const char stream_data[]
Definition: mlang.c:2327
static const WCHAR en_dech[]
Definition: mlang.c:148
static void test_Rfc1766ToLcid(void)
Definition: mlang.c:1410
static const WCHAR fr_de[]
Definition: mlang.c:160
static HRESULT WINAPI stream_Revert(IStream *iface)
Definition: mlang.c:2403
static LPCWSTR
Definition: mlang.c:48
static const WCHAR en_enus[]
Definition: mlang.c:142
static HRESULT WINAPI stream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *newpos)
Definition: mlang.c:2370
static void test_GetRfc1766Info(IMultiLanguage2 *iML2)
Definition: mlang.c:1539
static HRESULT WINAPI stream_SetSize(IStream *iface, ULARGE_INTEGER newsize)
Definition: mlang.c:2384
static const WCHAR en_deat[]
Definition: mlang.c:146
static void test_IMLangConvertCharset(IMultiLanguage *ml)
Definition: mlang.c:2265
static HRESULT WINAPI stream_Write(IStream *iface, const void *buf, ULONG len, ULONG *written)
Definition: mlang.c:2364
static const WCHAR de_dech[]
Definition: mlang.c:134
static HRESULT WINAPI stream_QueryInterface(IStream *iface, REFIID riid, void **obj)
Definition: mlang.c:2330
static const WCHAR fr_en[]
Definition: mlang.c:151
static void test_GetCharsetInfo_other(IMultiLanguage *ml)
Definition: mlang.c:1014
static const lcid_table_entry lcid_table[]
Definition: mlang.c:65
static void test_EnumCodePages(IMultiLanguage2 *iML2, DWORD flags)
Definition: mlang.c:783
static LPCSTR
Definition: mlang.c:46
static const WCHAR fr_engb[]
Definition: mlang.c:154
static HRESULT WINAPI stream_Commit(IStream *iface, DWORD flags)
Definition: mlang.c:2397
static HRESULT WINAPI stream_Read(IStream *iface, void *buf, ULONG len, ULONG *read)
Definition: mlang.c:2348
static void cpinfo_cmp(MIMECPINFO *cpinfo1, MIMECPINFO *cpinfo2)
Definition: mlang.c:702
static BOOL init_function_ptrs(void)
Definition: mlang.c:544
static void scriptinfo_cmp(SCRIPTINFO *sinfo1, SCRIPTINFO *sinfo2)
Definition: mlang.c:1059