ntoskrnl.exe/tests: Add some IOCTL_HID_WRITE_REPORT tests.
[wine.git] / dlls / mlang / mlang.c
blob82fa9a0515e5026d624ac6e98478146758c673c1
1 /*
2 * MLANG Class Factory
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2003,2004 Mike McCormack
6 * Copyright 2004,2005 Dmitry Timoshkov
7 * Copyright 2009 Detlef Riekenberg
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <stdarg.h>
26 #include <stdio.h>
28 #define COBJMACROS
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "objbase.h"
36 #include "rpcproxy.h"
37 #include "mlang.h"
38 #include "mimeole.h"
40 #include "wine/debug.h"
41 #include "wine/list.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(mlang);
45 #include "initguid.h"
47 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
48 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj);
49 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum);
51 static DWORD MLANG_tls_index; /* to store various per thead data */
53 /* FIXME:
54 * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
55 * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
58 typedef struct
60 const char *description;
61 UINT cp;
62 DWORD flags;
63 const char *web_charset;
64 const char *header_charset;
65 const char *body_charset;
66 const WCHAR *alias;
67 } MIME_CP_INFO;
69 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
70 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
72 static const MIME_CP_INFO arabic_cp[] =
74 { "Arabic (864)",
75 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
76 MIMECONTF_MIME_LATEST,
77 "ibm864", "ibm864", "ibm864" },
78 { "Arabic (1006)",
79 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
80 MIMECONTF_MIME_LATEST,
81 "ibm1006", "ibm1006", "ibm1006" },
82 { "Arabic (Windows)",
83 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
84 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
85 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
86 "windows-1256", "windows-1256", "windows-1256" },
87 { "Arabic (ISO)",
88 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
89 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
90 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
91 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
92 "iso-8859-6", "iso-8859-6", "iso-8859-6" }
94 static const MIME_CP_INFO baltic_cp[] =
96 { "Baltic (DOS)",
97 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
98 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
99 "ibm775", "ibm775", "ibm775" },
100 { "Baltic (Windows)",
101 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
102 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
103 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
104 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
105 "windows-1257", "windows-1257", "windows-1257" },
106 { "Baltic (ISO)",
107 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
108 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
109 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
110 MIMECONTF_MIME_LATEST,
111 "iso-8859-4", "iso-8859-4", "iso-8859-4" },
112 { "Estonian (ISO)",
113 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
114 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
115 "iso-8859-13", "iso-8859-13", "iso-8859-13" }
117 static const MIME_CP_INFO chinese_simplified_cp[] =
119 { "Chinese Simplified (Auto-Select)",
120 50936, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
121 MIMECONTF_MIME_LATEST,
122 "_autodetect_chs", "_autodetect_chs", "_autodetect_chs" },
123 { "Chinese Simplified (GB2312)",
124 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
125 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
126 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
127 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
128 "gb2312", "gb2312", "gb2312" },
129 { "Chinese Simplified (GB2312-80)",
130 20936, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
131 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
132 "x-cp20936", "x-cp20936", "x-cp20936" },
133 { "Chinese Simplified (HZ)",
134 52936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
135 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
136 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
137 MIMECONTF_MIME_LATEST,
138 "hz-gb-2312", "hz-gb-2312", "hz-gb-2312" },
139 { "Chinese Simplified (GB18030)",
140 54936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
141 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
142 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
143 MIMECONTF_MIME_LATEST,
144 "GB18030", "GB18030", "GB18030" },
145 { "Chinese Simplified (GBK)",
146 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
147 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
148 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
149 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
150 "gbk", "gbk", "gbk" }
152 static const MIME_CP_INFO chinese_traditional_cp[] =
154 { "Chinese Traditional (Auto-Select)",
155 50950, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
156 MIMECONTF_MIME_LATEST,
157 "_autodetect_cht", "_autodetect_cht", "_autodetect_cht" },
158 { "Chinese Traditional (Big5)",
159 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
160 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
161 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
162 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
163 "big5", "big5", "big5" },
164 { "Chinese Traditional (CNS)",
165 20000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
166 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
167 "x-Chinese-CNS", "x-Chinese-CNS", "x-Chinese-CNS" }
169 static const MIME_CP_INFO central_european_cp[] =
171 { "Central European (DOS)",
172 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
173 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
174 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
175 "ibm852", "ibm852", "ibm852" },
176 { "Central European (Windows)",
177 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
178 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
179 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
180 MIMECONTF_MIME_LATEST,
181 "windows-1250", "windows-1250", "windows-1250" },
182 { "Central European (Mac)",
183 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
184 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
185 "x-mac-ce", "x-mac-ce", "x-mac-ce" },
186 { "Central European (ISO)",
187 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
188 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
189 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
190 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
191 "iso-8859-2", "iso-8859-2", "iso-8859-2" }
193 static const MIME_CP_INFO cyrillic_cp[] =
195 { "OEM Cyrillic",
196 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
197 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
198 "ibm855", "ibm855", "ibm855" },
199 { "Cyrillic (DOS)",
200 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
201 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
202 MIMECONTF_MIME_LATEST,
203 "cp866", "cp866", "cp866" },
204 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
205 { "Cyrillic (KOI8-R)",
206 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
207 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
208 "koi8-r", "koi8-r", "koi8-r" },
209 #endif
210 { "Cyrillic (Windows)",
211 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
212 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
213 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
214 "windows-1251", "windows-1251", "windows-1251" },
215 { "Cyrillic (Mac)",
216 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
217 MIMECONTF_MIME_LATEST,
218 "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
219 { "Cyrillic (KOI8-R)",
220 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
221 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
222 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
223 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
224 "koi8-r", "koi8-r", "koi8-r" },
225 { "Cyrillic (KOI8-U)",
226 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
227 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
228 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
229 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
230 "koi8-u", "koi8-u", "koi8-u" },
231 { "Cyrillic (ISO)",
232 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
233 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
234 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
235 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
236 "iso-8859-5", "iso-8859-5", "iso-8859-5" }
238 static const MIME_CP_INFO greek_cp[] =
240 { "Greek (DOS)",
241 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
242 MIMECONTF_MIME_LATEST,
243 "ibm737", "ibm737", "ibm737" },
244 { "Greek, Modern (DOS)",
245 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
246 MIMECONTF_MIME_LATEST,
247 "ibm869", "ibm869", "ibm869" },
248 { "IBM EBCDIC (Greek Modern)",
249 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
250 MIMECONTF_MIME_LATEST,
251 "cp875", "cp875", "cp875" },
252 { "Greek (Windows)",
253 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
254 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
255 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
256 "windows-1253", "windows-1253", "windows-1253" },
257 { "Greek (Mac)",
258 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
259 MIMECONTF_MIME_LATEST,
260 "x-mac-greek", "x-mac-greek", "x-mac-greek" },
261 { "Greek (ISO)",
262 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
263 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
264 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
265 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
266 "iso-8859-7", "iso-8859-7", "iso-8859-7" }
268 static const MIME_CP_INFO hebrew_cp[] =
270 { "Hebrew (424)",
271 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
272 MIMECONTF_MIME_LATEST,
273 "ibm424", "ibm424", "ibm424" },
274 { "Hebrew (856)",
275 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
276 MIMECONTF_MIME_LATEST,
277 "cp856", "cp856", "cp856" },
278 { "Hebrew (DOS)",
279 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
280 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
281 MIMECONTF_MIME_LATEST,
282 "dos-862", "dos-862", "dos-862" },
283 { "Hebrew (Windows)",
284 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
285 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
286 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
287 "windows-1255", "windows-1255", "windows-1255" },
288 { "Hebrew (ISO-Visual)",
289 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
290 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
291 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
292 "iso-8859-8", "iso-8859-8", "iso-8859-8" }
294 static const MIME_CP_INFO japanese_cp[] =
296 { "Japanese (Auto-Select)",
297 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
298 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
299 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
300 "_autodetect", "_autodetect", "_autodetect" },
301 { "Japanese (EUC)",
302 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
303 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
304 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
305 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
306 "euc-jp", "euc-jp", "euc-jp" },
307 { "Japanese (JIS)",
308 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
309 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
310 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
311 MIMECONTF_MIME_IE4,
312 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
313 { "Japanese (JIS 0208-1990 and 0212-1990)",
314 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
315 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
316 "EUC-JP","EUC-JP","EUC-JP"},
317 { "Japanese (JIS-Allow 1 byte Kana)",
318 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
319 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
320 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
321 "csISO2022JP","iso-2022-jp","iso-2022-jp"},
322 { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
323 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
324 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
325 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
326 { "Japanese (Mac)",
327 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
328 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
329 "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
330 { "Japanese (Shift-JIS)",
331 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
332 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
333 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
334 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
335 "shift_jis", "iso-2022-jp", "iso-2022-jp" }
337 static const MIME_CP_INFO korean_cp[] =
339 { "Korean",
340 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
341 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
342 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
343 MIMECONTF_MIME_LATEST,
344 "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
346 static const MIME_CP_INFO thai_cp[] =
348 { "Thai (Windows)",
349 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
350 "ibm-thai", "ibm-thai", "ibm-thai" }
352 static const MIME_CP_INFO turkish_cp[] =
354 { "Turkish (DOS)",
355 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
356 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
357 "ibm857", "ibm857", "ibm857" },
358 { "IBM EBCDIC (Turkish Latin-5)",
359 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
360 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
361 "ibm1026", "ibm1026", "ibm1026" },
362 { "Turkish (Windows)",
363 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
364 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
365 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
366 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
367 "windows-1254", "windows-1254", "windows-1254" },
368 { "Turkish (Mac)",
369 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
370 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
371 "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
372 { "Latin 3 (ISO)",
373 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
374 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
375 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
376 "iso-8859-3", "iso-8859-3", "iso-8859-3" },
377 { "Turkish (ISO)",
378 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
379 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
380 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
381 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
382 "iso-8859-9", "iso-8859-9", "iso-8859-9" }
384 static const MIME_CP_INFO vietnamese_cp[] =
386 { "Vietnamese (Windows)",
387 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
388 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
389 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
390 MIMECONTF_MIME_LATEST,
391 "windows-1258", "windows-1258", "windows-1258" }
394 static const MIME_CP_INFO western_cp[] =
396 { "IBM EBCDIC (US-Canada)",
397 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
398 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
399 "ibm037", "ibm037", "ibm037" },
400 { "OEM United States",
401 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
402 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
403 "ibm437", "ibm437", "ibm437" },
404 { "IBM EBCDIC (International)",
405 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
406 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
407 "ibm500", "ibm500", "ibm500" },
408 { "Western European (DOS)",
409 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
410 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
411 "ibm850", "ibm850", "ibm850" },
412 { "Portuguese (DOS)",
413 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
414 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
415 "ibm860", "ibm860", "ibm860" },
416 { "Icelandic (DOS)",
417 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
418 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
419 "ibm861", "ibm861", "ibm861" },
420 { "French Canadian (DOS)",
421 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
422 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
423 "ibm863", "ibm863", "ibm863" },
424 { "Nordic (DOS)",
425 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
426 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
427 "ibm865", "ibm865", "ibm865" },
428 { "Western European (Windows)",
429 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
430 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
431 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
432 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
433 "windows-1252", "windows-1252", "iso-8859-1" },
434 { "Western European (Mac)",
435 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
436 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
437 "macintosh", "macintosh", "macintosh" },
438 { "Icelandic (Mac)",
439 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
440 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
441 "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
442 { "US-ASCII",
443 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
444 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
445 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
446 "us-ascii", "us-ascii", "us-ascii", L"ascii" },
447 { "Western European (ISO)",
448 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
449 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
450 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
451 MIMECONTF_MIME_LATEST,
452 "iso-8859-1", "iso-8859-1", "iso-8859-1" },
453 { "Latin 9 (ISO)",
454 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
455 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
456 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
457 MIMECONTF_MIME_LATEST,
458 "iso-8859-15", "iso-8859-15", "iso-8859-15" }
460 static const MIME_CP_INFO unicode_cp[] =
462 { "Unicode",
463 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
464 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
465 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
466 MIMECONTF_MIME_LATEST,
467 "unicode", "unicode", "unicode" },
468 { "Unicode (UTF-7)",
469 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
470 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
471 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
472 "utf-7", "utf-7", "utf-7" },
473 { "Unicode (UTF-8)",
474 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
475 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
476 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
477 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
478 "utf-8", "utf-8", "utf-8" }
481 static const struct mlang_data
483 const char *description;
484 UINT family_codepage;
485 UINT number_of_cp;
486 const MIME_CP_INFO *mime_cp_info;
487 const char *fixed_font;
488 const char *proportional_font;
489 SCRIPT_ID sid;
490 } mlang_data[] =
492 { "Arabic", 1256, ARRAY_SIZE(arabic_cp), arabic_cp,
493 "Simplified Arabic Fixed","Simplified Arabic", sidArabic },
494 { "Baltic", 1257, ARRAY_SIZE(baltic_cp), baltic_cp,
495 "Courier New","Arial", sidAsciiLatin },
496 { "Chinese Simplified", 936, ARRAY_SIZE(chinese_simplified_cp), chinese_simplified_cp,
497 "Simsun","Simsun", sidHan },
498 { "Chinese Traditional", 950, ARRAY_SIZE(chinese_traditional_cp), chinese_traditional_cp,
499 "MingLiu","New MingLiu", sidBopomofo },
500 { "Central European", 1250, ARRAY_SIZE(central_european_cp), central_european_cp,
501 "Courier New","Arial", sidAsciiLatin },
502 { "Cyrillic", 1251, ARRAY_SIZE(cyrillic_cp), cyrillic_cp,
503 "Courier New","Arial", sidCyrillic },
504 { "Greek", 1253, ARRAY_SIZE(greek_cp), greek_cp,
505 "Courier New","Arial", sidGreek },
506 { "Hebrew", 1255, ARRAY_SIZE(hebrew_cp), hebrew_cp,
507 "Miriam Fixed","David", sidHebrew },
508 { "Japanese", 932, ARRAY_SIZE(japanese_cp), japanese_cp,
509 "MS Gothic","MS PGothic", sidKana },
510 { "Korean", 949, ARRAY_SIZE(korean_cp), korean_cp,
511 "GulimChe","Gulim", sidHangul },
512 { "Thai", 874, ARRAY_SIZE(thai_cp), thai_cp,
513 "Tahoma","Tahoma", sidThai },
514 { "Turkish", 1254, ARRAY_SIZE(turkish_cp), turkish_cp,
515 "Courier New","Arial", sidAsciiLatin },
516 { "Vietnamese", 1258, ARRAY_SIZE(vietnamese_cp), vietnamese_cp,
517 "Courier New","Arial", sidAsciiLatin },
518 { "Western European", 1252, ARRAY_SIZE(western_cp), western_cp,
519 "Courier New","Arial", sidAsciiLatin },
520 { "Unicode", CP_UNICODE, ARRAY_SIZE(unicode_cp), unicode_cp,
521 "Courier New","Arial" }
524 struct font_list
526 struct list list_entry;
527 HFONT base_font;
528 HFONT font;
529 UINT charset;
532 static struct list font_cache = LIST_INIT(font_cache);
533 static CRITICAL_SECTION font_cache_critical;
534 static CRITICAL_SECTION_DEBUG font_cache_critical_debug =
536 0, 0, &font_cache_critical,
537 { &font_cache_critical_debug.ProcessLocksList, &font_cache_critical_debug.ProcessLocksList },
538 0, 0, { (DWORD_PTR)(__FILE__ ": font_cache_critical") }
540 static CRITICAL_SECTION font_cache_critical = { &font_cache_critical_debug, -1, 0, 0, 0, 0 };
542 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
544 static LONG dll_count;
547 * Japanese Detection and Conversion Functions
550 #define HANKATA(A) ((A >= 161) && (A <= 223))
551 #define ISEUC(A) ((A >= 161) && (A <= 254))
552 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
553 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
554 #define SJIS2(A) ((A >= 64) && (A <= 252))
555 #define ISMARU(A) ((A >= 202) && (A <= 206))
556 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
558 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
560 UINT code = 0;
561 DWORD i = 0;
562 unsigned char c1,c2;
564 while ((code == 0 || code == 51932) && i < count)
566 c1 = input[i];
567 if (c1 == 0x1b /* ESC */)
569 i++;
570 if (i >= count)
571 return code;
572 c1 = input[i];
573 if (c1 == '$')
575 i++;
576 if (i >= count)
577 return code;
578 c1 = input[i];
579 if (c1 =='B' || c1 == '@')
580 code = 50220;
582 if (c1 == 'K')
583 code = 50220;
585 else if (c1 >= 129)
587 i++;
588 if (i >= count)
589 return code;
590 c2 = input[i];
591 if NOTEUC(c1,c2)
592 code = 932;
593 else if (ISEUC(c1) && ISEUC(c2))
594 code = 51932;
595 else if (((c1 == 142)) && HANKATA(c2))
596 code = 51932;
598 i++;
600 return code;
603 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
605 unsigned char c1 = *p1;
606 unsigned char c2 = *p2;
607 int row = c1 < 95 ? 112 : 176;
608 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
610 *p1 = ((c1 + 1) >> 1) + row;
611 *p2 = c2 + cell;
614 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
616 unsigned char c1 = *p1;
617 unsigned char c2 = *p2;
618 int shift = c2 < 159;
619 int row = c1 < 160 ? 112 : 176;
620 int cell = shift ? (31 + (c2 > 127)): 126;
622 *p1 = ((c1 - row) << 1) - shift;
623 *p2 -= cell;
626 static int han2zen(unsigned char *p1, unsigned char *p2)
628 BOOL maru = FALSE;
629 BOOL nigori = FALSE;
630 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
631 131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
632 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
633 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
634 131,129,129 };
635 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
636 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
637 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
638 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
640 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
641 nigori = TRUE;
642 else if ((*p2 == 223) && (ISMARU(*p1)))
643 maru = TRUE;
645 if (*p1 >= 161 && *p1 <= 223)
647 unsigned char index = *p1 - 161;
648 *p1 = char1[index];
649 *p2 = char2[index];
652 if (maru || nigori)
654 if (nigori)
656 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
657 (*p2)++;
658 else if ((*p1 == 131) && (*p2 == 69))
659 *p2 = 148;
661 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
662 *p2+= 2;
664 return 1;
667 return 0;
671 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
673 DWORD i = 0;
674 int j = 0;
675 unsigned char p2,p;
676 BOOL shifted = FALSE;
678 while (i < count)
680 p = input[i];
681 if (p == 0x1b /* ESC */)
683 i++;
684 if (i >= count)
685 return 0;
686 p2 = input[i];
687 if (p2 == '$' || p2 =='(')
688 i++;
689 if (p2 == 'K' || p2 =='$')
690 shifted = TRUE;
691 else
692 shifted = FALSE;
694 else
696 if (shifted)
698 i++;
699 if (i >= count)
700 return 0;
701 p2 = input[i];
702 jis2sjis(&p,&p2);
703 output[j++]=p;
704 output[j++]=p2;
706 else
708 output[j++] = p;
711 i++;
713 return j;
716 static inline int exit_shift(LPSTR out, int c)
718 if (out)
720 out[c] = 0x1b;
721 out[c+1] = '(';
722 out[c+2] = 'B';
724 return 3;
727 static inline int enter_shift(LPSTR out, int c)
729 if (out)
731 out[c] = 0x1b;
732 out[c+1] = '$';
733 out[c+2] = 'B';
735 return 3;
739 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
741 DWORD i = 0;
742 int j = 0;
743 unsigned char p2,p;
744 BOOL shifted = FALSE;
746 while (i < count)
748 p = input[i] & 0xff;
749 if (p == 10 || p == 13) /* NL and CR */
751 if (shifted)
753 shifted = FALSE;
754 j += exit_shift(output,j);
756 if (output)
757 output[j++] = p;
758 else
759 j++;
761 else
763 if (SJIS1(p))
765 i++;
766 if (i >= count)
767 return 0;
768 p2 = input[i] & 0xff;
769 if (SJIS2(p2))
771 sjis2jis(&p,&p2);
772 if (!shifted)
774 shifted = TRUE;
775 j+=enter_shift(output,j);
779 if (output)
781 output[j++]=p;
782 output[j++]=p2;
784 else
785 j+=2;
787 else
789 if (HANKATA(p))
791 if ((i+1) >= count)
792 return 0;
793 p2 = input[i+1] & 0xff;
794 i+=han2zen(&p,&p2);
795 sjis2jis(&p,&p2);
796 if (!shifted)
798 shifted = TRUE;
799 j+=enter_shift(output,j);
801 if (output)
803 output[j++]=p;
804 output[j++]=p2;
806 else
807 j+=2;
809 else
811 if (shifted)
813 shifted = FALSE;
814 j += exit_shift(output,j);
816 if (output)
817 output[j++]=p;
818 else
819 j++;
823 i++;
825 if (shifted)
826 j += exit_shift(output,j);
827 return j;
830 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
831 LPWSTR output, DWORD out_count)
833 CHAR *sjis_string;
834 UINT rc = 0;
835 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
836 rc = ConvertJIS2SJIS(input,count,sjis_string);
837 if (rc)
839 TRACE("%s\n",debugstr_an(sjis_string,rc));
840 if (output)
841 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
842 else
843 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
845 HeapFree(GetProcessHeap(),0,sjis_string);
846 return rc;
850 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
851 LPWSTR output, DWORD out_count)
853 CHAR *sjis_string;
854 UINT rc = 0;
855 int code = DetectJapaneseCode(input,count);
856 TRACE("Japanese code %i\n",code);
858 switch (code)
860 case 0:
861 if (output)
862 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
863 else
864 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
865 break;
867 case 932:
868 if (output)
869 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
870 else
871 rc = MultiByteToWideChar(932,0,input,count,0,0);
872 break;
874 case 51932:
875 if (output)
876 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
877 else
878 rc = MultiByteToWideChar(20932,0,input,count,0,0);
879 break;
881 case 50220:
882 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
883 rc = ConvertJIS2SJIS(input,count,sjis_string);
884 if (rc)
886 TRACE("%s\n",debugstr_an(sjis_string,rc));
887 if (output)
888 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
889 else
890 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
892 HeapFree(GetProcessHeap(),0,sjis_string);
893 break;
895 return rc;
898 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
899 LPSTR output, DWORD out_count)
901 CHAR *sjis_string;
902 INT len;
903 UINT rc = 0;
905 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
906 sjis_string = HeapAlloc(GetProcessHeap(),0,len);
907 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
908 TRACE("%s\n",debugstr_an(sjis_string,len));
910 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
911 if (out_count >= rc)
913 ConvertSJIS2JIS(sjis_string, len, output);
915 HeapFree(GetProcessHeap(),0,sjis_string);
916 return rc;
921 * Dll lifetime tracking declaration
923 static void LockModule(void)
925 InterlockedIncrement(&dll_count);
928 static void UnlockModule(void)
930 InterlockedDecrement(&dll_count);
933 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
935 switch(fdwReason) {
936 case DLL_PROCESS_ATTACH:
937 MLANG_tls_index = TlsAlloc();
938 DisableThreadLibraryCalls(hInstDLL);
939 break;
940 case DLL_PROCESS_DETACH:
941 if (lpv) break;
942 TlsFree(MLANG_tls_index);
943 break;
945 return TRUE;
948 HRESULT WINAPI ConvertINetMultiByteToUnicode(
949 LPDWORD pdwMode,
950 DWORD dwEncoding,
951 LPCSTR pSrcStr,
952 LPINT pcSrcSize,
953 LPWSTR pDstStr,
954 LPINT pcDstSize)
956 INT src_len = -1;
958 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
959 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
961 if (!pcDstSize)
962 return E_FAIL;
964 if (!pcSrcSize)
965 pcSrcSize = &src_len;
967 if (!*pcSrcSize)
969 *pcDstSize = 0;
970 return S_OK;
973 /* forwarding euc-jp to EUC-JP */
974 if (dwEncoding == 51932)
975 dwEncoding = 20932;
977 switch (dwEncoding)
979 case CP_UNICODE:
980 if (*pcSrcSize == -1)
981 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
982 *pcDstSize = min(*pcSrcSize, *pcDstSize);
983 *pcSrcSize *= sizeof(WCHAR);
984 if (pDstStr)
985 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
986 break;
988 case 50220:
989 case 50221:
990 case 50222:
991 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
992 break;
993 case 50932:
994 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
995 break;
997 default:
998 if (*pcSrcSize == -1)
999 *pcSrcSize = lstrlenA(pSrcStr);
1001 if (pDstStr)
1002 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
1003 else
1004 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
1005 break;
1008 if (!*pcDstSize)
1009 return E_FAIL;
1011 return S_OK;
1014 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
1015 LPDWORD pdwMode,
1016 DWORD dwEncoding,
1017 LPCWSTR pSrcStr,
1018 LPINT pcSrcSize,
1019 LPSTR pDstStr,
1020 LPINT pcDstSize)
1022 INT destsz, size;
1023 INT src_len = -1;
1025 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
1026 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1028 if (!pcDstSize)
1029 return S_OK;
1031 if (!pcSrcSize)
1032 pcSrcSize = &src_len;
1034 destsz = (pDstStr) ? *pcDstSize : 0;
1035 *pcDstSize = 0;
1037 if (!pSrcStr || !*pcSrcSize)
1038 return S_OK;
1040 if (*pcSrcSize == -1)
1041 *pcSrcSize = lstrlenW(pSrcStr);
1043 /* forwarding euc-jp to EUC-JP */
1044 if (dwEncoding == 51932)
1045 dwEncoding = 20932;
1047 if (dwEncoding == CP_UNICODE)
1049 if (*pcSrcSize == -1)
1050 *pcSrcSize = lstrlenW(pSrcStr);
1052 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1053 if (pDstStr)
1054 memmove(pDstStr, pSrcStr, size);
1056 if (size >= destsz)
1057 goto fail;
1059 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1061 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1062 if (!size)
1063 goto fail;
1065 if (pDstStr)
1067 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1068 destsz);
1069 if (!size)
1070 goto fail;
1074 else
1076 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1077 NULL, 0, NULL, NULL);
1078 if (!size)
1079 goto fail;
1081 if (pDstStr)
1083 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1084 pDstStr, destsz, NULL, NULL);
1085 if (!size)
1086 goto fail;
1090 *pcDstSize = size;
1091 return S_OK;
1093 fail:
1094 *pcSrcSize = 0;
1095 *pcDstSize = 0;
1096 return E_FAIL;
1099 HRESULT WINAPI ConvertINetString(
1100 LPDWORD pdwMode,
1101 DWORD dwSrcEncoding,
1102 DWORD dwDstEncoding,
1103 LPCSTR pSrcStr,
1104 LPINT pcSrcSize,
1105 LPSTR pDstStr,
1106 LPINT pcDstSize
1109 TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1110 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1112 if (dwSrcEncoding == CP_UNICODE)
1114 INT cSrcSizeW;
1115 if (pcSrcSize && *pcSrcSize != -1)
1117 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1118 pcSrcSize = &cSrcSizeW;
1120 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1122 else if (dwDstEncoding == CP_UNICODE)
1124 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1125 *pcDstSize *= sizeof(WCHAR);
1126 return hr;
1128 else
1130 INT cDstSizeW;
1131 LPWSTR pDstStrW;
1132 HRESULT hr;
1134 TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1136 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1137 if (hr != S_OK)
1138 return hr;
1140 pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1141 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1142 if (hr == S_OK)
1143 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1145 HeapFree(GetProcessHeap(), 0, pDstStrW);
1146 return hr;
1150 static HRESULT GetFamilyCodePage(
1151 UINT uiCodePage,
1152 UINT* puiFamilyCodePage)
1154 UINT i, n;
1156 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1158 if (!puiFamilyCodePage) return S_FALSE;
1160 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1162 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1164 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1166 *puiFamilyCodePage = mlang_data[i].family_codepage;
1167 return S_OK;
1172 return S_FALSE;
1175 HRESULT WINAPI IsConvertINetStringAvailable(
1176 DWORD dwSrcEncoding,
1177 DWORD dwDstEncoding)
1179 UINT src_family, dst_family;
1181 TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
1183 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1184 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1185 return S_FALSE;
1187 if (src_family == dst_family) return S_OK;
1189 /* we can convert any codepage to/from unicode */
1190 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1192 return S_FALSE;
1195 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1197 CHAR buffer[MAX_RFC1766_NAME];
1198 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1199 INT i;
1201 if (n)
1203 i = PRIMARYLANGID(lcid);
1204 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1205 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1206 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1208 buffer[n - 1] = '-';
1209 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1210 if (!i)
1211 buffer[n - 1] = '\0';
1213 else
1214 i = 0;
1216 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1217 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1219 return E_FAIL;
1222 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1224 WCHAR buffer[MAX_RFC1766_NAME];
1225 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1226 INT i;
1228 if (n)
1230 i = PRIMARYLANGID(lcid);
1231 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1232 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1233 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1235 buffer[n - 1] = '-';
1236 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1237 if (!i)
1238 buffer[n - 1] = '\0';
1240 else
1241 i = 0;
1243 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1244 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1246 return E_FAIL;
1249 HRESULT WINAPI LcidToRfc1766A(
1250 LCID lcid,
1251 LPSTR pszRfc1766,
1252 INT nChar)
1254 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1255 if (!pszRfc1766)
1256 return E_INVALIDARG;
1258 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1261 HRESULT WINAPI LcidToRfc1766W(
1262 LCID lcid,
1263 LPWSTR pszRfc1766,
1264 INT nChar)
1266 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1267 if (!pszRfc1766)
1268 return E_INVALIDARG;
1270 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1273 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1275 RFC1766INFO info;
1276 ULONG num;
1278 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1280 if (!wcsicmp(info.wszRfc1766, rfc1766))
1282 *lcid = info.lcid;
1283 return S_OK;
1285 if (lstrlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1287 *lcid = PRIMARYLANGID(info.lcid);
1288 return S_OK;
1292 return E_FAIL;
1295 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1297 IEnumRfc1766 *enumrfc1766;
1298 HRESULT hr;
1300 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1302 if (!pLocale || !pszRfc1766)
1303 return E_INVALIDARG;
1305 hr = EnumRfc1766_create(0, &enumrfc1766);
1306 if (FAILED(hr))
1307 return hr;
1309 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1310 IEnumRfc1766_Release(enumrfc1766);
1312 return hr;
1315 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1317 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1319 if (!rfc1766A)
1320 return E_INVALIDARG;
1322 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1323 rfc1766W[MAX_RFC1766_NAME] = 0;
1325 return Rfc1766ToLcidW(lcid, rfc1766W);
1328 static HRESULT map_font(HDC hdc, DWORD codepages, HFONT src_font, HFONT *dst_font)
1330 struct font_list *font_list_entry;
1331 CHARSETINFO charset_info;
1332 HFONT new_font, old_font;
1333 LOGFONTW font_attr;
1334 DWORD mask, Csb[2];
1335 BOOL found_cached;
1336 UINT charset;
1337 BOOL ret;
1338 UINT i;
1340 if (hdc == NULL || src_font == NULL) return E_FAIL;
1342 for (i = 0; i < 32; i++)
1344 mask = (DWORD)(1 << i);
1345 if (codepages & mask)
1347 Csb[0] = mask;
1348 Csb[1] = 0x0;
1349 ret = TranslateCharsetInfo(Csb, &charset_info, TCI_SRCFONTSIG);
1350 if (!ret) continue;
1352 /* use cached font if possible */
1353 found_cached = FALSE;
1354 EnterCriticalSection(&font_cache_critical);
1355 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1357 if (font_list_entry->charset == charset_info.ciCharset &&
1358 font_list_entry->base_font == src_font)
1360 if (dst_font != NULL)
1361 *dst_font = font_list_entry->font;
1362 found_cached = TRUE;
1365 LeaveCriticalSection(&font_cache_critical);
1366 if (found_cached) return S_OK;
1368 GetObjectW(src_font, sizeof(font_attr), &font_attr);
1369 font_attr.lfCharSet = (BYTE)charset_info.ciCharset;
1370 font_attr.lfWidth = 0;
1371 font_attr.lfFaceName[0] = 0;
1372 new_font = CreateFontIndirectW(&font_attr);
1373 if (new_font == NULL) continue;
1375 old_font = SelectObject(hdc, new_font);
1376 charset = GetTextCharset(hdc);
1377 SelectObject(hdc, old_font);
1378 if (charset == charset_info.ciCharset)
1380 font_list_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_list_entry));
1381 if (font_list_entry == NULL) return E_OUTOFMEMORY;
1383 font_list_entry->base_font = src_font;
1384 font_list_entry->font = new_font;
1385 font_list_entry->charset = charset;
1387 EnterCriticalSection(&font_cache_critical);
1388 list_add_tail(&font_cache, &font_list_entry->list_entry);
1389 LeaveCriticalSection(&font_cache_critical);
1391 if (dst_font != NULL)
1392 *dst_font = new_font;
1393 return S_OK;
1398 return E_FAIL;
1401 static HRESULT release_font(HFONT font)
1403 struct font_list *font_list_entry;
1404 HRESULT hr;
1406 hr = E_FAIL;
1407 EnterCriticalSection(&font_cache_critical);
1408 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1410 if (font_list_entry->font == font)
1412 list_remove(&font_list_entry->list_entry);
1413 DeleteObject(font);
1414 HeapFree(GetProcessHeap(), 0, font_list_entry);
1415 hr = S_OK;
1416 break;
1419 LeaveCriticalSection(&font_cache_critical);
1421 return hr;
1424 static HRESULT clear_font_cache(void)
1426 struct font_list *font_list_entry;
1427 struct font_list *font_list_entry2;
1429 EnterCriticalSection(&font_cache_critical);
1430 LIST_FOR_EACH_ENTRY_SAFE(font_list_entry, font_list_entry2, &font_cache, struct font_list, list_entry)
1432 list_remove(&font_list_entry->list_entry);
1433 DeleteObject(font_list_entry->font);
1434 HeapFree(GetProcessHeap(), 0, font_list_entry);
1436 LeaveCriticalSection(&font_cache_critical);
1438 return S_OK;
1441 /******************************************************************************
1442 * MLANG ClassFactory
1444 typedef struct {
1445 IClassFactory IClassFactory_iface;
1446 LONG ref;
1447 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1448 } IClassFactoryImpl;
1450 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1452 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1455 struct object_creation_info
1457 const CLSID *clsid;
1458 LPCSTR szClassName;
1459 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1462 static const struct object_creation_info object_creation[] =
1464 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1465 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1468 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1470 TRACE("%s\n", debugstr_guid(riid) );
1472 if (IsEqualGUID(riid, &IID_IUnknown)
1473 || IsEqualGUID(riid, &IID_IClassFactory))
1475 IClassFactory_AddRef(iface);
1476 *ppobj = iface;
1477 return S_OK;
1480 *ppobj = NULL;
1481 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1482 return E_NOINTERFACE;
1485 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1487 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1488 return InterlockedIncrement(&This->ref);
1491 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1493 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1494 ULONG ref = InterlockedDecrement(&This->ref);
1496 if (ref == 0)
1498 TRACE("Destroying %p\n", This);
1499 HeapFree(GetProcessHeap(), 0, This);
1502 return ref;
1505 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1506 REFIID riid, void **ppobj)
1508 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1509 HRESULT hres;
1510 LPUNKNOWN punk;
1512 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1514 *ppobj = NULL;
1515 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1516 if (SUCCEEDED(hres)) {
1517 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1518 IUnknown_Release(punk);
1520 TRACE("returning (%p) -> %x\n", *ppobj, hres);
1521 return hres;
1524 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1526 if (dolock)
1527 LockModule();
1528 else
1529 UnlockModule();
1531 return S_OK;
1534 static const IClassFactoryVtbl MLANGCF_Vtbl =
1536 MLANGCF_QueryInterface,
1537 MLANGCF_AddRef,
1538 MLANGCF_Release,
1539 MLANGCF_CreateInstance,
1540 MLANGCF_LockServer
1543 /******************************************************************
1544 * DllGetClassObject (MLANG.@)
1546 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1548 unsigned int i;
1549 IClassFactoryImpl *factory;
1551 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1553 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1554 && ! IsEqualGUID( &IID_IUnknown, iid) )
1555 return E_NOINTERFACE;
1557 for (i = 0; i < ARRAY_SIZE(object_creation); i++)
1559 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1560 break;
1563 if (i == ARRAY_SIZE(object_creation))
1565 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1566 return CLASS_E_CLASSNOTAVAILABLE;
1569 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1571 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1572 if (factory == NULL) return E_OUTOFMEMORY;
1574 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1575 factory->ref = 1;
1577 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1579 *ppv = &factory->IClassFactory_iface;
1581 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1583 return S_OK;
1587 /******************************************************************************/
1589 typedef struct tagMLang_impl
1591 IMLangFontLink IMLangFontLink_iface;
1592 IMultiLanguage IMultiLanguage_iface;
1593 IMultiLanguage3 IMultiLanguage3_iface;
1594 IMLangFontLink2 IMLangFontLink2_iface;
1595 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1596 LONG ref;
1597 DWORD total_cp, total_scripts;
1598 } MLang_impl;
1600 /******************************************************************************/
1602 typedef struct tagEnumCodePage_impl
1604 IEnumCodePage IEnumCodePage_iface;
1605 LONG ref;
1606 MIMECPINFO *cpinfo;
1607 DWORD total, pos;
1608 } EnumCodePage_impl;
1610 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1612 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1615 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1616 IEnumCodePage* iface,
1617 REFIID riid,
1618 void** ppvObject)
1620 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1622 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1624 if (IsEqualGUID(riid, &IID_IUnknown)
1625 || IsEqualGUID(riid, &IID_IEnumCodePage))
1627 IEnumCodePage_AddRef(iface);
1628 TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
1629 *ppvObject = &This->IEnumCodePage_iface;
1630 return S_OK;
1633 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1634 return E_NOINTERFACE;
1637 static ULONG WINAPI fnIEnumCodePage_AddRef(
1638 IEnumCodePage* iface)
1640 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1641 return InterlockedIncrement(&This->ref);
1644 static ULONG WINAPI fnIEnumCodePage_Release(
1645 IEnumCodePage* iface)
1647 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1648 ULONG ref = InterlockedDecrement(&This->ref);
1650 TRACE("%p ref = %d\n", This, ref);
1651 if (ref == 0)
1653 TRACE("Destroying %p\n", This);
1654 HeapFree(GetProcessHeap(), 0, This->cpinfo);
1655 HeapFree(GetProcessHeap(), 0, This);
1658 return ref;
1661 static HRESULT WINAPI fnIEnumCodePage_Clone(
1662 IEnumCodePage* iface,
1663 IEnumCodePage** ppEnum)
1665 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1666 FIXME("%p %p\n", This, ppEnum);
1667 return E_NOTIMPL;
1670 static HRESULT WINAPI fnIEnumCodePage_Next(
1671 IEnumCodePage* iface,
1672 ULONG celt,
1673 PMIMECPINFO rgelt,
1674 ULONG* pceltFetched)
1676 ULONG i;
1677 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1679 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1681 if (!pceltFetched) return S_FALSE;
1682 *pceltFetched = 0;
1684 if (!rgelt) return S_FALSE;
1686 if (This->pos + celt > This->total)
1687 celt = This->total - This->pos;
1689 if (!celt) return S_FALSE;
1691 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1692 *pceltFetched = celt;
1693 This->pos += celt;
1695 for (i = 0; i < celt; i++)
1697 TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
1698 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1699 rgelt[i].uiFamilyCodePage,
1700 wine_dbgstr_w(rgelt[i].wszDescription),
1701 wine_dbgstr_w(rgelt[i].wszWebCharset),
1702 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1703 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1704 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1705 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1706 rgelt[i].bGDICharset);
1708 return S_OK;
1711 static HRESULT WINAPI fnIEnumCodePage_Reset(
1712 IEnumCodePage* iface)
1714 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1716 TRACE("%p\n", This);
1718 This->pos = 0;
1719 return S_OK;
1722 static HRESULT WINAPI fnIEnumCodePage_Skip(
1723 IEnumCodePage* iface,
1724 ULONG celt)
1726 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1728 TRACE("%p %u\n", This, celt);
1730 if (celt >= This->total) return S_FALSE;
1732 This->pos += celt;
1733 return S_OK;
1736 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1738 fnIEnumCodePage_QueryInterface,
1739 fnIEnumCodePage_AddRef,
1740 fnIEnumCodePage_Release,
1741 fnIEnumCodePage_Clone,
1742 fnIEnumCodePage_Next,
1743 fnIEnumCodePage_Reset,
1744 fnIEnumCodePage_Skip
1747 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1748 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1750 EnumCodePage_impl *ecp;
1751 MIMECPINFO *cpinfo;
1752 UINT i, n;
1754 TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1756 if (!grfFlags) /* enumerate internal data base of encodings */
1757 grfFlags = MIMECONTF_MIME_LATEST;
1759 ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1760 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1761 ecp->ref = 1;
1762 ecp->pos = 0;
1763 ecp->total = 0;
1764 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1766 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1768 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1769 ecp->total++;
1773 ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1774 sizeof(MIMECPINFO) * ecp->total);
1775 cpinfo = ecp->cpinfo;
1777 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1779 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1781 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1782 fill_cp_info(&mlang_data[i], n, cpinfo++);
1786 TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
1788 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1790 return S_OK;
1793 /******************************************************************************/
1795 typedef struct tagEnumScript_impl
1797 IEnumScript IEnumScript_iface;
1798 LONG ref;
1799 SCRIPTINFO *script_info;
1800 DWORD total, pos;
1801 } EnumScript_impl;
1803 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1805 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1808 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1809 IEnumScript* iface,
1810 REFIID riid,
1811 void** ppvObject)
1813 EnumScript_impl *This = impl_from_IEnumScript( iface );
1815 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1817 if (IsEqualGUID(riid, &IID_IUnknown)
1818 || IsEqualGUID(riid, &IID_IEnumScript))
1820 IEnumScript_AddRef(iface);
1821 TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
1822 *ppvObject = &This->IEnumScript_iface;
1823 return S_OK;
1826 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1827 return E_NOINTERFACE;
1830 static ULONG WINAPI fnIEnumScript_AddRef(
1831 IEnumScript* iface)
1833 EnumScript_impl *This = impl_from_IEnumScript( iface );
1834 return InterlockedIncrement(&This->ref);
1837 static ULONG WINAPI fnIEnumScript_Release(
1838 IEnumScript* iface)
1840 EnumScript_impl *This = impl_from_IEnumScript( iface );
1841 ULONG ref = InterlockedDecrement(&This->ref);
1843 TRACE("%p ref = %d\n", This, ref);
1844 if (ref == 0)
1846 TRACE("Destroying %p\n", This);
1847 HeapFree(GetProcessHeap(), 0, This->script_info);
1848 HeapFree(GetProcessHeap(), 0, This);
1851 return ref;
1854 static HRESULT WINAPI fnIEnumScript_Clone(
1855 IEnumScript* iface,
1856 IEnumScript** ppEnum)
1858 EnumScript_impl *This = impl_from_IEnumScript( iface );
1859 FIXME("%p %p: stub!\n", This, ppEnum);
1860 return E_NOTIMPL;
1863 static HRESULT WINAPI fnIEnumScript_Next(
1864 IEnumScript* iface,
1865 ULONG celt,
1866 PSCRIPTINFO rgelt,
1867 ULONG* pceltFetched)
1869 EnumScript_impl *This = impl_from_IEnumScript( iface );
1871 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1873 if (!pceltFetched || !rgelt) return E_FAIL;
1875 *pceltFetched = 0;
1877 if (This->pos + celt > This->total)
1878 celt = This->total - This->pos;
1880 if (!celt) return S_FALSE;
1882 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1883 *pceltFetched = celt;
1884 This->pos += celt;
1886 return S_OK;
1889 static HRESULT WINAPI fnIEnumScript_Reset(
1890 IEnumScript* iface)
1892 EnumScript_impl *This = impl_from_IEnumScript( iface );
1894 TRACE("%p\n", This);
1896 This->pos = 0;
1897 return S_OK;
1900 static HRESULT WINAPI fnIEnumScript_Skip(
1901 IEnumScript* iface,
1902 ULONG celt)
1904 EnumScript_impl *This = impl_from_IEnumScript( iface );
1906 TRACE("%p %u\n", This, celt);
1908 if (celt >= This->total) return S_FALSE;
1910 This->pos += celt;
1911 return S_OK;
1914 static const IEnumScriptVtbl IEnumScript_vtbl =
1916 fnIEnumScript_QueryInterface,
1917 fnIEnumScript_AddRef,
1918 fnIEnumScript_Release,
1919 fnIEnumScript_Clone,
1920 fnIEnumScript_Next,
1921 fnIEnumScript_Reset,
1922 fnIEnumScript_Skip
1925 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1926 LANGID LangId, IEnumScript** ppEnumScript )
1928 EnumScript_impl *es;
1929 UINT i;
1931 TRACE("%p, %08x, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1933 if (!dwFlags) /* enumerate all available scripts */
1934 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1936 es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1937 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1938 es->ref = 1;
1939 es->pos = 0;
1940 /* do not enumerate unicode flavours */
1941 es->total = ARRAY_SIZE(mlang_data) - 1;
1942 es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1944 for (i = 0; i < es->total; i++)
1946 es->script_info[i].ScriptId = i;
1947 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1948 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1949 es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1950 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1951 es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1952 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1953 es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1956 TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
1958 *ppEnumScript = &es->IEnumScript_iface;
1960 return S_OK;
1963 /******************************************************************************/
1965 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1967 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1970 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1971 IMLangFontLink* iface,
1972 REFIID riid,
1973 void** ppvObject)
1975 MLang_impl *This = impl_from_IMLangFontLink( iface );
1976 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1979 static ULONG WINAPI fnIMLangFontLink_AddRef(
1980 IMLangFontLink* iface)
1982 MLang_impl *This = impl_from_IMLangFontLink( iface );
1983 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1986 static ULONG WINAPI fnIMLangFontLink_Release(
1987 IMLangFontLink* iface)
1989 MLang_impl *This = impl_from_IMLangFontLink( iface );
1990 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1993 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1994 IMLangFontLink* iface,
1995 WCHAR ch_src,
1996 DWORD* codepages)
1998 MLang_impl *This = impl_from_IMLangFontLink( iface );
1999 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
2002 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
2003 IMLangFontLink* iface,
2004 const WCHAR* src,
2005 LONG src_len,
2006 DWORD priority_cp,
2007 DWORD* codepages,
2008 LONG* ret_len)
2010 MLang_impl *This = impl_from_IMLangFontLink( iface );
2011 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
2012 codepages, ret_len);
2015 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
2016 IMLangFontLink* iface,
2017 UINT codepage,
2018 DWORD* codepages)
2020 MLang_impl *This = impl_from_IMLangFontLink( iface );
2021 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
2024 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
2025 IMLangFontLink* iface,
2026 DWORD codepages,
2027 UINT def_codepage,
2028 UINT* codepage)
2030 MLang_impl *This = impl_from_IMLangFontLink(iface);
2031 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
2032 def_codepage, codepage);
2035 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
2036 IMLangFontLink* iface,
2037 HDC hdc,
2038 HFONT hfont,
2039 DWORD* codepages)
2041 MLang_impl *This = impl_from_IMLangFontLink(iface);
2042 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
2045 static HRESULT WINAPI fnIMLangFontLink_MapFont(
2046 IMLangFontLink* iface,
2047 HDC hDC,
2048 DWORD dwCodePages,
2049 HFONT hSrcFont,
2050 HFONT* phDestFont)
2052 TRACE("(%p)->%p %08x %p %p\n",iface, hDC, dwCodePages, hSrcFont, phDestFont);
2054 return map_font(hDC, dwCodePages, hSrcFont, phDestFont);
2057 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
2058 IMLangFontLink* iface,
2059 HFONT hFont)
2061 TRACE("(%p)->%p\n",iface, hFont);
2063 return release_font(hFont);
2066 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
2067 IMLangFontLink* iface)
2069 TRACE("(%p)\n",iface);
2071 return clear_font_cache();
2075 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
2077 fnIMLangFontLink_QueryInterface,
2078 fnIMLangFontLink_AddRef,
2079 fnIMLangFontLink_Release,
2080 fnIMLangFontLink_GetCharCodePages,
2081 fnIMLangFontLink_GetStrCodePages,
2082 fnIMLangFontLink_CodePageToCodePages,
2083 fnIMLangFontLink_CodePagesToCodePage,
2084 fnIMLangFontLink_GetFontCodePages,
2085 fnIMLangFontLink_MapFont,
2086 fnIMLangFontLink_ReleaseFont,
2087 fnIMLangFontLink_ResetFontMapping,
2090 /******************************************************************************/
2092 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
2094 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
2097 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
2098 IMultiLanguage* iface,
2099 REFIID riid,
2100 void** obj)
2102 MLang_impl *This = impl_from_IMultiLanguage( iface );
2103 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
2106 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
2108 MLang_impl *This = impl_from_IMultiLanguage( iface );
2109 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
2112 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
2114 MLang_impl *This = impl_from_IMultiLanguage( iface );
2115 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
2118 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
2119 IMultiLanguage* iface,
2120 UINT* cp)
2122 MLang_impl *This = impl_from_IMultiLanguage( iface );
2123 TRACE("(%p, %p)\n", This, cp);
2124 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
2127 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
2128 IMultiLanguage* iface,
2129 UINT uiCodePage,
2130 PMIMECPINFO pCodePageInfo)
2132 UINT i, n;
2133 MLang_impl *This = impl_from_IMultiLanguage( iface );
2135 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
2137 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2139 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2141 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2143 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2144 return S_OK;
2149 return S_FALSE;
2152 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
2153 IMultiLanguage* iface,
2154 UINT cp,
2155 UINT* family_cp)
2157 MLang_impl *This = impl_from_IMultiLanguage( iface );
2158 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2161 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2162 IMultiLanguage* iface,
2163 DWORD grfFlags,
2164 IEnumCodePage** ppEnumCodePage)
2166 MLang_impl *This = impl_from_IMultiLanguage( iface );
2168 TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
2170 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2173 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2174 IMultiLanguage* iface,
2175 BSTR Charset,
2176 PMIMECSETINFO pCharsetInfo)
2178 MLang_impl *This = impl_from_IMultiLanguage( iface );
2179 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2182 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2183 IMultiLanguage* iface,
2184 DWORD src_enc,
2185 DWORD dst_enc)
2187 MLang_impl *This = impl_from_IMultiLanguage( iface );
2188 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2191 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2192 IMultiLanguage* iface,
2193 DWORD* mode,
2194 DWORD src_enc,
2195 DWORD dst_enc,
2196 BYTE* src,
2197 UINT* src_size,
2198 BYTE* dest,
2199 UINT* dest_size)
2201 MLang_impl *This = impl_from_IMultiLanguage( iface );
2202 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2203 dst_enc, src, src_size, dest, dest_size);
2206 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2207 IMultiLanguage* iface,
2208 DWORD* mode,
2209 DWORD src_enc,
2210 CHAR* src,
2211 UINT* src_size,
2212 WCHAR* dest,
2213 UINT* dest_size)
2215 MLang_impl *This = impl_from_IMultiLanguage( iface );
2216 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2217 mode, src_enc, src, src_size, dest, dest_size);
2220 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2221 IMultiLanguage* iface,
2222 DWORD* mode,
2223 DWORD encoding,
2224 WCHAR* src,
2225 UINT* src_size,
2226 CHAR* dest,
2227 UINT* dest_size)
2229 MLang_impl *This = impl_from_IMultiLanguage(iface);
2230 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2231 mode, encoding, src, src_size, dest, dest_size);
2234 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2235 IMultiLanguage* iface)
2237 MLang_impl *This = impl_from_IMultiLanguage( iface );
2238 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2241 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2242 IMultiLanguage* iface,
2243 LCID lcid,
2244 BSTR* pbstrRfc1766)
2246 MLang_impl *This = impl_from_IMultiLanguage(iface);
2247 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2250 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2251 IMultiLanguage* iface,
2252 LCID* locale,
2253 BSTR rfc1766)
2255 MLang_impl *This = impl_from_IMultiLanguage(iface);
2256 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2259 /******************************************************************************/
2261 typedef struct tagEnumRfc1766_impl
2263 IEnumRfc1766 IEnumRfc1766_iface;
2264 LONG ref;
2265 RFC1766INFO *info;
2266 DWORD total, pos;
2267 } EnumRfc1766_impl;
2269 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2271 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2274 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2275 IEnumRfc1766 *iface,
2276 REFIID riid,
2277 void** ppvObject)
2279 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2281 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2283 if (IsEqualGUID(riid, &IID_IUnknown)
2284 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2286 IEnumRfc1766_AddRef(iface);
2287 TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
2288 *ppvObject = &This->IEnumRfc1766_iface;
2289 return S_OK;
2292 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2293 return E_NOINTERFACE;
2296 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2297 IEnumRfc1766 *iface)
2299 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2300 return InterlockedIncrement(&This->ref);
2303 static ULONG WINAPI fnIEnumRfc1766_Release(
2304 IEnumRfc1766 *iface)
2306 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2307 ULONG ref = InterlockedDecrement(&This->ref);
2309 TRACE("%p ref = %d\n", This, ref);
2310 if (ref == 0)
2312 TRACE("Destroying %p\n", This);
2313 HeapFree(GetProcessHeap(), 0, This->info);
2314 HeapFree(GetProcessHeap(), 0, This);
2316 return ref;
2319 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2320 IEnumRfc1766 *iface,
2321 IEnumRfc1766 **ppEnum)
2323 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2325 FIXME("%p %p\n", This, ppEnum);
2326 return E_NOTIMPL;
2329 static HRESULT WINAPI fnIEnumRfc1766_Next(
2330 IEnumRfc1766 *iface,
2331 ULONG celt,
2332 PRFC1766INFO rgelt,
2333 ULONG *pceltFetched)
2335 ULONG i;
2336 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2338 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
2340 if (!pceltFetched) return S_FALSE;
2341 *pceltFetched = 0;
2343 if (!rgelt) return S_FALSE;
2345 if (This->pos + celt > This->total)
2346 celt = This->total - This->pos;
2348 if (!celt) return S_FALSE;
2350 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2351 *pceltFetched = celt;
2352 This->pos += celt;
2354 for (i = 0; i < celt; i++)
2356 TRACE("#%u: %08x %s %s\n",
2357 i, rgelt[i].lcid,
2358 wine_dbgstr_w(rgelt[i].wszRfc1766),
2359 wine_dbgstr_w(rgelt[i].wszLocaleName));
2361 return S_OK;
2364 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2365 IEnumRfc1766 *iface)
2367 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2369 TRACE("%p\n", This);
2371 This->pos = 0;
2372 return S_OK;
2375 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2376 IEnumRfc1766 *iface,
2377 ULONG celt)
2379 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2381 TRACE("%p %u\n", This, celt);
2383 if (celt >= This->total) return S_FALSE;
2385 This->pos += celt;
2386 return S_OK;
2389 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2391 fnIEnumRfc1766_QueryInterface,
2392 fnIEnumRfc1766_AddRef,
2393 fnIEnumRfc1766_Release,
2394 fnIEnumRfc1766_Clone,
2395 fnIEnumRfc1766_Next,
2396 fnIEnumRfc1766_Reset,
2397 fnIEnumRfc1766_Skip
2400 struct enum_locales_data
2402 RFC1766INFO *info;
2403 DWORD total, allocated;
2406 static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
2408 WCHAR *end;
2409 struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
2410 RFC1766INFO *info;
2412 TRACE("%s\n", debugstr_w(locale));
2414 if (data->total >= data->allocated)
2416 data->allocated += 32;
2417 data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2418 if (!data->info) return FALSE;
2421 info = &data->info[data->total];
2423 info->lcid = wcstol(locale, &end, 16);
2424 if (*end) /* invalid number */
2425 return FALSE;
2427 info->wszRfc1766[0] = 0;
2428 lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
2430 info->wszLocaleName[0] = 0;
2431 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2432 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2434 data->total++;
2436 return TRUE;
2439 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2441 EnumRfc1766_impl *rfc;
2442 struct enum_locales_data data;
2444 TRACE("%04x, %p\n", LangId, ppEnum);
2446 rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2447 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2448 rfc->ref = 1;
2449 rfc->pos = 0;
2450 rfc->total = 0;
2452 data.total = 0;
2453 data.allocated = 160;
2454 data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2455 if (!data.info)
2457 HeapFree(GetProcessHeap(), 0, rfc);
2458 return E_OUTOFMEMORY;
2461 TlsSetValue(MLANG_tls_index, &data);
2462 EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
2463 TlsSetValue(MLANG_tls_index, NULL);
2465 TRACE("enumerated %d rfc1766 structures\n", data.total);
2467 if (!data.total)
2469 HeapFree(GetProcessHeap(), 0, data.info);
2470 HeapFree(GetProcessHeap(), 0, rfc);
2471 return E_FAIL;
2474 rfc->info = data.info;
2475 rfc->total = data.total;
2477 *ppEnum = &rfc->IEnumRfc1766_iface;
2478 return S_OK;
2481 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2482 IMultiLanguage *iface,
2483 IEnumRfc1766 **ppEnumRfc1766)
2485 MLang_impl *This = impl_from_IMultiLanguage( iface );
2487 TRACE("%p %p\n", This, ppEnumRfc1766);
2489 return EnumRfc1766_create(0, ppEnumRfc1766);
2492 /******************************************************************************/
2494 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2495 IMultiLanguage* iface,
2496 LCID Locale,
2497 PRFC1766INFO pRfc1766Info)
2499 LCTYPE type = LOCALE_SLANGUAGE;
2501 TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
2503 if (!pRfc1766Info)
2504 return E_INVALIDARG;
2506 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2507 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2508 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2510 if (!SUBLANGID(Locale))
2511 type = LOCALE_SENGLANGUAGE; /* suppress country */
2513 else
2515 if (!SUBLANGID(Locale)) {
2516 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2517 return E_FAIL;
2521 pRfc1766Info->lcid = Locale;
2522 pRfc1766Info->wszRfc1766[0] = 0;
2523 pRfc1766Info->wszLocaleName[0] = 0;
2525 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2526 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2527 return S_OK;
2529 /* Locale not supported */
2530 return E_INVALIDARG;
2533 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2534 IMultiLanguage* iface,
2535 UINT src_cp,
2536 UINT dst_cp,
2537 DWORD prop,
2538 IMLangConvertCharset** convert_charset)
2540 MLang_impl *This = impl_from_IMultiLanguage(iface);
2541 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2544 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2546 fnIMultiLanguage_QueryInterface,
2547 fnIMultiLanguage_AddRef,
2548 fnIMultiLanguage_Release,
2549 fnIMultiLanguage_GetNumberOfCodePageInfo,
2550 fnIMultiLanguage_GetCodePageInfo,
2551 fnIMultiLanguage_GetFamilyCodePage,
2552 fnIMultiLanguage_EnumCodePages,
2553 fnIMultiLanguage_GetCharsetInfo,
2554 fnIMultiLanguage_IsConvertible,
2555 fnIMultiLanguage_ConvertString,
2556 fnIMultiLanguage_ConvertStringToUnicode,
2557 fnIMultiLanguage_ConvertStringFromUnicode,
2558 fnIMultiLanguage_ConvertStringReset,
2559 fnIMultiLanguage_GetRfc1766FromLcid,
2560 fnIMultiLanguage_GetLcidFromRfc1766,
2561 fnIMultiLanguage_EnumRfc1766,
2562 fnIMultiLanguage_GetRfc1766Info,
2563 fnIMultiLanguage_CreateConvertCharset,
2567 /******************************************************************************/
2569 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2571 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2574 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2575 IMultiLanguage3* iface,
2576 REFIID riid,
2577 void** obj)
2579 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2581 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2583 if (IsEqualGUID(riid, &IID_IUnknown) ||
2584 IsEqualGUID(riid, &IID_IMultiLanguage))
2586 *obj = &This->IMultiLanguage_iface;
2588 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2589 IsEqualGUID(riid, &IID_IMLangFontLink))
2591 *obj = &This->IMLangFontLink_iface;
2593 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2595 *obj = &This->IMLangFontLink2_iface;
2597 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2598 IsEqualGUID(riid, &IID_IMultiLanguage3))
2600 *obj = &This->IMultiLanguage3_iface;
2602 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2604 *obj = &This->IMLangLineBreakConsole_iface;
2606 else
2608 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2609 *obj = NULL;
2610 return E_NOINTERFACE;
2613 IMultiLanguage3_AddRef(iface);
2614 return S_OK;
2617 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2619 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2620 return InterlockedIncrement(&This->ref);
2623 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2625 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2626 ULONG ref = InterlockedDecrement(&This->ref);
2628 TRACE("(%p)->(%d)\n", This, ref);
2629 if (ref == 0)
2631 HeapFree(GetProcessHeap(), 0, This);
2632 UnlockModule();
2635 return ref;
2638 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2639 IMultiLanguage3* iface,
2640 UINT* pcCodePage)
2642 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2644 TRACE("%p, %p\n", This, pcCodePage);
2646 if (!pcCodePage) return E_INVALIDARG;
2648 *pcCodePage = This->total_cp;
2649 return S_OK;
2652 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2654 CHARSETINFO csi;
2656 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2657 TCI_SRCCODEPAGE))
2658 mime_cp_info->bGDICharset = csi.ciCharset;
2659 else
2660 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2662 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2663 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2664 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2665 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
2666 mime_cp_info->wszDescription, ARRAY_SIZE(mime_cp_info->wszDescription));
2667 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
2668 mime_cp_info->wszWebCharset, ARRAY_SIZE(mime_cp_info->wszWebCharset));
2669 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
2670 mime_cp_info->wszHeaderCharset, ARRAY_SIZE(mime_cp_info->wszHeaderCharset));
2671 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
2672 mime_cp_info->wszBodyCharset, ARRAY_SIZE(mime_cp_info->wszBodyCharset));
2674 MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
2675 mime_cp_info->wszFixedWidthFont, ARRAY_SIZE(mime_cp_info->wszFixedWidthFont));
2676 MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
2677 mime_cp_info->wszProportionalFont, ARRAY_SIZE(mime_cp_info->wszProportionalFont));
2679 TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
2680 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2681 mime_cp_info->uiFamilyCodePage,
2682 wine_dbgstr_w(mime_cp_info->wszDescription),
2683 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2684 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2685 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2686 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2687 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2688 mime_cp_info->bGDICharset);
2691 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2692 IMultiLanguage3* iface,
2693 UINT uiCodePage,
2694 LANGID LangId,
2695 PMIMECPINFO pCodePageInfo)
2697 UINT i, n;
2698 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2700 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2702 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2704 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2706 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2708 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2709 return S_OK;
2714 return S_FALSE;
2717 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2718 IMultiLanguage3* iface,
2719 UINT uiCodePage,
2720 UINT* puiFamilyCodePage)
2722 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2725 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2726 IMultiLanguage3* iface,
2727 DWORD grfFlags,
2728 LANGID LangId,
2729 IEnumCodePage** ppEnumCodePage)
2731 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2733 TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2735 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2738 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2739 IMultiLanguage3* iface,
2740 BSTR Charset,
2741 PMIMECSETINFO pCharsetInfo)
2743 UINT i, n;
2744 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2746 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2748 if (!pCharsetInfo) return E_FAIL;
2750 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2752 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2754 WCHAR csetW[MAX_MIMECSET_NAME];
2756 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
2757 if (!lstrcmpiW(Charset, csetW))
2759 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2760 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2761 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2762 return S_OK;
2764 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2766 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2767 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2768 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2769 return S_OK;
2774 /* FIXME:
2775 * Since we do not support charsets like iso-2022-jp and do not have
2776 * them in our database as a primary (web_charset) encoding this loop
2777 * does an attempt to 'approximate' charset name by header_charset.
2779 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2781 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2783 WCHAR csetW[MAX_MIMECSET_NAME];
2785 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
2786 if (!lstrcmpiW(Charset, csetW))
2788 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2789 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2790 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2791 return S_OK;
2796 return E_FAIL;
2799 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2800 IMultiLanguage3* iface,
2801 DWORD dwSrcEncoding,
2802 DWORD dwDstEncoding)
2804 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2807 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2808 IMultiLanguage3* iface,
2809 DWORD* pdwMode,
2810 DWORD dwSrcEncoding,
2811 DWORD dwDstEncoding,
2812 BYTE* pSrcStr,
2813 UINT* pcSrcSize,
2814 BYTE* pDstStr,
2815 UINT* pcDstSize)
2817 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2818 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2821 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2822 IMultiLanguage3* iface,
2823 DWORD* pdwMode,
2824 DWORD dwEncoding,
2825 CHAR* pSrcStr,
2826 UINT* pcSrcSize,
2827 WCHAR* pDstStr,
2828 UINT* pcDstSize)
2830 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2831 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2834 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2835 IMultiLanguage3* iface,
2836 DWORD* pdwMode,
2837 DWORD dwEncoding,
2838 WCHAR* pSrcStr,
2839 UINT* pcSrcSize,
2840 CHAR* pDstStr,
2841 UINT* pcDstSize)
2843 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2844 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2847 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2848 IMultiLanguage3* iface)
2850 FIXME("\n");
2851 return E_NOTIMPL;
2854 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2855 IMultiLanguage3* iface,
2856 LCID lcid,
2857 BSTR* pbstrRfc1766)
2859 WCHAR buf[MAX_RFC1766_NAME];
2861 TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
2862 if (!pbstrRfc1766)
2863 return E_INVALIDARG;
2865 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2867 *pbstrRfc1766 = SysAllocString( buf );
2868 return S_OK;
2870 return E_FAIL;
2873 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2874 IMultiLanguage3* iface,
2875 LCID* pLocale,
2876 BSTR bstrRfc1766)
2878 HRESULT hr;
2879 IEnumRfc1766 *rfc1766;
2881 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2883 if (!pLocale || !bstrRfc1766)
2884 return E_INVALIDARG;
2886 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2887 if (FAILED(hr))
2888 return hr;
2890 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2892 IEnumRfc1766_Release(rfc1766);
2893 return hr;
2896 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2897 IMultiLanguage3* iface,
2898 LANGID LangId,
2899 IEnumRfc1766** ppEnumRfc1766)
2901 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2903 TRACE("%p %p\n", This, ppEnumRfc1766);
2905 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2908 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2909 IMultiLanguage3* iface,
2910 LCID Locale,
2911 LANGID LangId,
2912 PRFC1766INFO pRfc1766Info)
2914 static LANGID last_lang = -1;
2915 LCTYPE type = LOCALE_SLANGUAGE;
2917 TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2919 if (!pRfc1766Info)
2920 return E_INVALIDARG;
2922 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2923 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2924 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2926 if (!SUBLANGID(Locale))
2927 type = LOCALE_SENGLANGUAGE; /* suppress country */
2929 else
2931 if (!SUBLANGID(Locale)) {
2932 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2933 return E_FAIL;
2937 pRfc1766Info->lcid = Locale;
2938 pRfc1766Info->wszRfc1766[0] = 0;
2939 pRfc1766Info->wszLocaleName[0] = 0;
2941 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2942 (last_lang != LangId)) {
2943 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2944 last_lang = LangId;
2947 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2948 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2949 return S_OK;
2951 /* Locale not supported */
2952 return E_INVALIDARG;
2955 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2956 IMultiLanguage3* iface,
2957 UINT src_cp,
2958 UINT dst_cp,
2959 DWORD prop,
2960 IMLangConvertCharset** convert_charset)
2962 HRESULT hr;
2964 TRACE("(%u %u 0x%08x %p)\n", src_cp, dst_cp, prop, convert_charset);
2966 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2967 if (FAILED(hr)) return hr;
2969 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2972 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2973 IMultiLanguage3* iface,
2974 DWORD* pdwMode,
2975 DWORD dwFlag,
2976 WCHAR* lpFallBack,
2977 DWORD dwSrcEncoding,
2978 DWORD dwDstEncoding,
2979 IStream* pstmIn,
2980 IStream* pstmOut)
2982 char *src, *dst = NULL;
2983 INT srclen, dstlen;
2984 STATSTG stat;
2985 HRESULT hr;
2987 TRACE("%p %0x8 %s %u %u %p %p\n",
2988 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2990 FIXME("dwFlag and lpFallBack not handled\n");
2992 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2993 if (FAILED(hr)) return hr;
2995 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
2996 if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
2998 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
2999 if (FAILED(hr)) goto exit;
3001 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
3002 if (FAILED(hr)) goto exit;
3004 if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
3006 hr = E_OUTOFMEMORY;
3007 goto exit;
3009 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
3010 if (FAILED(hr)) goto exit;
3012 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
3014 exit:
3015 HeapFree(GetProcessHeap(), 0, src);
3016 HeapFree(GetProcessHeap(), 0, dst);
3017 return hr;
3020 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
3021 IMultiLanguage3* iface,
3022 DWORD* pdwMode,
3023 DWORD dwEncoding,
3024 CHAR* pSrcStr,
3025 UINT* pcSrcSize,
3026 WCHAR* pDstStr,
3027 UINT* pcDstSize,
3028 DWORD dwFlag,
3029 WCHAR* lpFallBack)
3031 if (dwFlag || lpFallBack)
3032 FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
3033 dwFlag, dwFlag, lpFallBack);
3035 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
3036 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3039 /*****************************************************************************
3040 * MultiLanguage2::ConvertStringToUnicodeEx
3042 * Translates the multibyte string from the specified code page to Unicode.
3044 * PARAMS
3045 * see ConvertStringToUnicode
3046 * dwFlag
3047 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
3048 * instead unconvertible characters.
3050 * RETURNS
3051 * S_OK Success.
3052 * S_FALSE The conversion is not supported.
3053 * E_FAIL Some error has occurred.
3055 * TODO: handle dwFlag and lpFallBack
3057 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
3058 IMultiLanguage3* This,
3059 DWORD* pdwMode,
3060 DWORD dwEncoding,
3061 WCHAR* pSrcStr,
3062 UINT* pcSrcSize,
3063 CHAR* pDstStr,
3064 UINT* pcDstSize,
3065 DWORD dwFlag,
3066 WCHAR* lpFallBack)
3068 FIXME("\n");
3069 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
3070 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3073 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
3074 IMultiLanguage3* iface,
3075 DWORD dwFlag,
3076 DWORD dwPrefWinCodePage,
3077 IStream* pstmIn,
3078 DetectEncodingInfo* lpEncoding,
3079 INT* pnScores)
3081 FIXME("\n");
3082 return E_NOTIMPL;
3085 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
3086 IMultiLanguage3* iface,
3087 DWORD dwFlag,
3088 DWORD dwPrefWinCodePage,
3089 CHAR* pSrcStr,
3090 INT* pcSrcSize,
3091 DetectEncodingInfo* lpEncoding,
3092 INT* pnScores)
3094 FIXME("\n");
3095 return E_NOTIMPL;
3098 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
3099 IMultiLanguage3* iface,
3100 UINT uiCodePage,
3101 HWND hwnd)
3103 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
3106 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
3107 IMultiLanguage3* iface,
3108 UINT uiCodePage,
3109 LCID lcid,
3110 LPWSTR lpWideCharStr,
3111 int cchWideChar)
3113 /* Find first instance */
3114 unsigned int i,n;
3116 TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
3117 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3119 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3121 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3123 MultiByteToWideChar(CP_ACP, 0,
3124 mlang_data[i].mime_cp_info[n].description,
3125 -1, lpWideCharStr, cchWideChar);
3126 return S_OK;
3131 return S_FALSE;
3134 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
3135 IMultiLanguage3* iface,
3136 UINT uiCodePage)
3138 TRACE("%u\n", uiCodePage);
3140 /* FIXME: the installable set is usually larger than the set of valid codepages */
3141 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
3144 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
3145 IMultiLanguage3* iface,
3146 MIMECONTF dwSource)
3148 FIXME("0x%08x\n", dwSource);
3149 return S_OK;
3152 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
3153 IMultiLanguage3* iface,
3154 UINT* pnScripts)
3156 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3158 TRACE("%p %p\n", This, pnScripts);
3160 if (!pnScripts) return S_FALSE;
3162 *pnScripts = This->total_scripts;
3163 return S_OK;
3166 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3167 IMultiLanguage3* iface,
3168 DWORD dwFlags,
3169 LANGID LangId,
3170 IEnumScript** ppEnumScript)
3172 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3174 TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3176 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3179 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3180 IMultiLanguage3* iface,
3181 UINT uiCodePage,
3182 HWND hwnd,
3183 DWORD dwfIODControl)
3185 unsigned int i;
3186 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3188 TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
3190 /* quick check for kernel32 supported code pages */
3191 if (IsValidCodePage(uiCodePage))
3192 return S_OK;
3194 /* check for mlang supported code pages */
3195 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3197 UINT n;
3198 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3200 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3201 return S_OK;
3205 if (dwfIODControl != CPIOD_PEEK)
3206 FIXME("Request to install codepage language pack not handled\n");
3208 return S_FALSE;
3211 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3212 IMultiLanguage3 *iface,
3213 DWORD dwFlags,
3214 LPCWSTR lpWideCharStr,
3215 UINT cchWideChar,
3216 UINT *puiPreferredCodePages,
3217 UINT nPreferredCodePages,
3218 UINT *puiDetectedCodePages,
3219 UINT *pnDetectedCodePages,
3220 WCHAR *lpSpecialChar)
3222 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3224 FIXME("(%p)->(%08x %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3225 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3226 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3227 debugstr_w(lpSpecialChar));
3229 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3230 return E_INVALIDARG;
3232 puiDetectedCodePages[0] = CP_UTF8;
3233 *pnDetectedCodePages = 1;
3234 return S_OK;
3237 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3238 IMultiLanguage3 *iface,
3239 DWORD dwFlags,
3240 IStream *pStrIn,
3241 UINT *puiPreferredCodePages,
3242 UINT nPreferredCodePages,
3243 UINT *puiDetectedCodePages,
3244 UINT *pnDetectedCodePages,
3245 WCHAR *lpSpecialChar)
3247 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3249 FIXME("(%p)->(%08x %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3250 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3251 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3252 debugstr_w(lpSpecialChar));
3254 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3255 return E_INVALIDARG;
3257 puiDetectedCodePages[0] = CP_UTF8;
3258 *pnDetectedCodePages = 1;
3259 return S_OK;
3262 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3264 fnIMultiLanguage3_QueryInterface,
3265 fnIMultiLanguage3_AddRef,
3266 fnIMultiLanguage3_Release,
3267 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3268 fnIMultiLanguage3_GetCodePageInfo,
3269 fnIMultiLanguage3_GetFamilyCodePage,
3270 fnIMultiLanguage3_EnumCodePages,
3271 fnIMultiLanguage3_GetCharsetInfo,
3272 fnIMultiLanguage3_IsConvertible,
3273 fnIMultiLanguage3_ConvertString,
3274 fnIMultiLanguage3_ConvertStringToUnicode,
3275 fnIMultiLanguage3_ConvertStringFromUnicode,
3276 fnIMultiLanguage3_ConvertStringReset,
3277 fnIMultiLanguage3_GetRfc1766FromLcid,
3278 fnIMultiLanguage3_GetLcidFromRfc1766,
3279 fnIMultiLanguage3_EnumRfc1766,
3280 fnIMultiLanguage3_GetRfc1766Info,
3281 fnIMultiLanguage3_CreateConvertCharset,
3282 fnIMultiLanguage3_ConvertStringInIStream,
3283 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3284 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3285 fnIMultiLanguage3_DetectCodepageInIStream,
3286 fnIMultiLanguage3_DetectInputCodepage,
3287 fnIMultiLanguage3_ValidateCodePage,
3288 fnIMultiLanguage3_GetCodePageDescription,
3289 fnIMultiLanguage3_IsCodePageInstallable,
3290 fnIMultiLanguage3_SetMimeDBSource,
3291 fnIMultiLanguage3_GetNumberOfScripts,
3292 fnIMultiLanguage3_EnumScripts,
3293 fnIMultiLanguage3_ValidateCodePageEx,
3294 fnIMultiLanguage3_DetectOutboundCodePage,
3295 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3298 /******************************************************************************/
3300 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3302 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3305 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3306 IMLangFontLink2 * iface,
3307 REFIID riid,
3308 void** ppvObject)
3310 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3311 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3314 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3316 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3317 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3320 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3322 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3323 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3326 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3327 WCHAR ch_src, DWORD *ret_codepages)
3329 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3330 unsigned int i;
3332 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3334 *ret_codepages = 0;
3336 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3338 BOOL used_dc;
3339 CHAR buf;
3341 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3342 &ch_src, 1, &buf, 1, NULL, &used_dc);
3344 /* If default char is not used, current codepage include the given symbol */
3345 if (!used_dc)
3347 DWORD codepages;
3349 IMLangFontLink2_CodePageToCodePages(iface,
3350 mlang_data[i].family_codepage, &codepages);
3351 *ret_codepages |= codepages;
3354 return S_OK;
3357 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3358 const WCHAR *src, LONG src_len, DWORD priority_cp,
3359 DWORD *codepages, LONG *ret_len)
3361 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3362 LONG i;
3363 DWORD cps = 0;
3365 TRACE("(%p)->(%s:%d %x %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3366 codepages, ret_len);
3368 if (codepages) *codepages = 0;
3369 if (ret_len) *ret_len = 0;
3371 if (!src || !src_len || src_len < 0)
3372 return E_INVALIDARG;
3374 for (i = 0; i < src_len; i++)
3376 DWORD cp;
3377 HRESULT ret;
3379 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3380 if (ret != S_OK) return E_FAIL;
3382 if (!cps) cps = cp;
3383 else cps &= cp;
3385 /* FIXME: not tested */
3386 if (priority_cp & cps) break;
3389 if (codepages) *codepages = cps;
3390 if (ret_len) *ret_len = min( i + 1, src_len );
3391 return S_OK;
3394 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3395 UINT codepage,
3396 DWORD *codepages)
3398 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3399 CHARSETINFO cs;
3400 BOOL rc;
3402 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3404 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3405 if (rc)
3407 *codepages = cs.fs.fsCsb[0];
3408 TRACE("resulting codepages 0x%x\n", *codepages);
3409 return S_OK;
3412 TRACE("codepage not found\n");
3413 *codepages = 0;
3414 return E_FAIL;
3417 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3418 DWORD codepages, UINT def_codepage, UINT *codepage)
3420 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3421 DWORD mask = 0;
3422 CHARSETINFO cs;
3423 BOOL rc;
3424 UINT i;
3426 TRACE("(%p)->(0x%x %u %p)\n", This, codepages, def_codepage, codepage);
3428 *codepage = 0;
3430 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3431 if (rc && (codepages & cs.fs.fsCsb[0]))
3433 TRACE("Found Default Codepage\n");
3434 *codepage = def_codepage;
3435 return S_OK;
3438 for (i = 0; i < 32; i++)
3440 mask = 1 << i;
3441 if (codepages & mask)
3443 DWORD Csb[2];
3444 Csb[0] = mask;
3445 Csb[1] = 0x0;
3446 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3447 if (!rc)
3448 continue;
3450 TRACE("Falling back to least significant found CodePage %u\n",
3451 cs.ciACP);
3452 *codepage = cs.ciACP;
3453 return S_OK;
3457 TRACE("no codepage found\n");
3458 return E_FAIL;
3461 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3462 HDC hdc, HFONT hfont, DWORD *codepages)
3464 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3465 FONTSIGNATURE fontsig;
3466 HFONT old_font;
3468 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3470 old_font = SelectObject(hdc, hfont);
3471 GetTextCharsetInfo(hdc, &fontsig, 0);
3472 SelectObject(hdc, old_font);
3474 *codepages = fontsig.fsCsb[0];
3475 TRACE("ret 0x%x\n", fontsig.fsCsb[0]);
3477 return S_OK;
3480 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3481 HFONT hFont)
3483 TRACE("(%p)->%p\n",This, hFont);
3485 return release_font(hFont);
3488 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3490 TRACE("(%p)\n",This);
3492 return clear_font_cache();
3495 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3496 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3498 HFONT old_font;
3500 TRACE("(%p)->%p %08x %04x %p\n",This, hDC, dwCodePages, chSrc, pFont);
3502 if (!hDC) return E_FAIL;
3504 if (dwCodePages != 0)
3506 old_font = GetCurrentObject(hDC, OBJ_FONT);
3507 return map_font(hDC, dwCodePages, old_font, pFont);
3509 else
3511 if (pFont == NULL) return E_INVALIDARG;
3512 FIXME("the situation where dwCodepages is set to zero is not implemented\n");
3513 return E_FAIL;
3517 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3518 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3520 DWORD size;
3521 GLYPHSET *gs;
3523 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3525 if (!puiRanges) return E_INVALIDARG;
3526 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3527 if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3529 GetFontUnicodeRanges(hDC, gs);
3530 *puiRanges = gs->cRanges;
3531 if (pUranges)
3533 UINT i;
3534 for (i = 0; i < gs->cRanges; i++)
3536 if (i >= *puiRanges) break;
3537 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3538 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3540 *puiRanges = i;
3542 HeapFree(GetProcessHeap(), 0, gs);
3543 return S_OK;
3546 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3547 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3548 SCRIPTFONTINFO *pScriptFont)
3550 UINT i, j;
3552 TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3554 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3556 for (i = 0, j = 0; i < ARRAY_SIZE(mlang_data); i++)
3558 if (sid == mlang_data[i].sid)
3560 if (pScriptFont)
3562 if (j >= *puiFonts) break;
3564 pScriptFont[j].scripts = (SCRIPT_IDS)1 << mlang_data[i].sid;
3565 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3567 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
3568 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3570 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3572 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
3573 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3576 j++;
3579 *puiFonts = j;
3580 return S_OK;
3583 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3584 UINT uiCodePage, SCRIPT_ID *pSid)
3586 UINT i;
3588 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3590 if (uiCodePage == CP_UNICODE) return E_FAIL;
3592 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3594 if (uiCodePage == mlang_data[i].family_codepage)
3596 if (pSid) *pSid = mlang_data[i].sid;
3597 return S_OK;
3600 return E_FAIL;
3603 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3605 fnIMLangFontLink2_QueryInterface,
3606 fnIMLangFontLink2_AddRef,
3607 fnIMLangFontLink2_Release,
3608 fnIMLangFontLink2_GetCharCodePages,
3609 fnIMLangFontLink2_GetStrCodePages,
3610 fnIMLangFontLink2_CodePageToCodePages,
3611 fnIMLangFontLink2_CodePagesToCodePage,
3612 fnIMLangFontLink2_GetFontCodePages,
3613 fnIMLangFontLink2_ReleaseFont,
3614 fnIMLangFontLink2_ResetFontMapping,
3615 fnIMLangFontLink2_MapFont,
3616 fnIMLangFontLink2_GetFontUnicodeRanges,
3617 fnIMLangFontLink2_GetScriptFontInfo,
3618 fnIMLangFontLink2_CodePageToScriptID
3621 /******************************************************************************/
3623 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3625 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3628 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3629 IMLangLineBreakConsole* iface,
3630 REFIID riid,
3631 void** ppvObject)
3633 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3634 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3637 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3638 IMLangLineBreakConsole* iface )
3640 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3641 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3644 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3645 IMLangLineBreakConsole* iface )
3647 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3648 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3651 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3652 IMLangLineBreakConsole* iface,
3653 IMLangString* pSrcMLStr,
3654 LONG lSrcPos,
3655 LONG lSrcLen,
3656 LONG cMinColumns,
3657 LONG cMaxColumns,
3658 LONG* plLineLen,
3659 LONG* plSkipLen)
3661 FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3662 return E_NOTIMPL;
3665 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3666 IMLangLineBreakConsole* iface,
3667 LCID locale,
3668 const WCHAR* pszSrc,
3669 LONG cchSrc,
3670 LONG cMaxColumns,
3671 LONG* pcchLine,
3672 LONG* pcchSkip )
3674 FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3676 *pcchLine = cchSrc;
3677 *pcchSkip = 0;
3678 return S_OK;
3681 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3682 IMLangLineBreakConsole* iface,
3683 LCID locale,
3684 UINT uCodePage,
3685 const CHAR* pszSrc,
3686 LONG cchSrc,
3687 LONG cMaxColumns,
3688 LONG* pcchLine,
3689 LONG* pcchSkip)
3691 LONG i, line = cchSrc, skip = 0;
3693 FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3695 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3697 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3699 if (pszSrc[i] == ' ')
3701 while (i >= 0 && pszSrc[i] == ' ')
3703 i--;
3704 line--;
3705 skip++;
3707 break;
3711 *pcchLine = line;
3712 *pcchSkip = skip;
3713 return S_OK;
3716 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3718 fnIMLangLineBreakConsole_QueryInterface,
3719 fnIMLangLineBreakConsole_AddRef,
3720 fnIMLangLineBreakConsole_Release,
3721 fnIMLangLineBreakConsole_BreakLineML,
3722 fnIMLangLineBreakConsole_BreakLineW,
3723 fnIMLangLineBreakConsole_BreakLineA
3726 struct convert_charset {
3727 IMLangConvertCharset IMLangConvertCharset_iface;
3728 LONG ref;
3730 UINT src_cp;
3731 UINT dst_cp;
3734 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3736 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3739 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3741 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3743 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3745 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3747 *obj = &This->IMLangConvertCharset_iface;
3748 IMLangConvertCharset_AddRef(iface);
3749 return S_OK;
3752 *obj = NULL;
3753 return E_NOINTERFACE;
3756 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3758 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3759 ULONG ref = InterlockedIncrement(&This->ref);
3760 TRACE("(%p)->(%u)\n", This, ref);
3761 return ref;
3764 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3766 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3767 ULONG ref = InterlockedDecrement(&This->ref);
3769 TRACE("(%p)->(%u)\n", This, ref);
3770 if (!ref)
3772 HeapFree(GetProcessHeap(), 0, This);
3773 UnlockModule();
3776 return ref;
3779 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3780 UINT src_cp, UINT dst_cp, DWORD prop)
3782 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3784 TRACE("(%p)->(%u %u 0x%08x)\n", This, src_cp, dst_cp, prop);
3786 prop &= ~MLCONVCHARF_USEDEFCHAR;
3787 if (prop)
3788 FIXME("property 0x%08x not supported\n", prop);
3790 This->src_cp = src_cp;
3791 This->dst_cp = dst_cp;
3793 return S_OK;
3796 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3798 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3800 TRACE("(%p)->(%p)\n", This, src_cp);
3802 if (!src_cp) return E_INVALIDARG;
3803 *src_cp = This->src_cp;
3804 return S_OK;
3807 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3809 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3811 TRACE("(%p)->(%p)\n", This, dst_cp);
3813 if (!dst_cp) return E_INVALIDARG;
3814 *dst_cp = This->dst_cp;
3815 return S_OK;
3818 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3820 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3821 FIXME("(%p)->(%p): stub\n", This, prop);
3822 return E_NOTIMPL;
3825 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3826 UINT *src_size, BYTE *dest, UINT *dest_size)
3828 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3829 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3830 return E_NOTIMPL;
3833 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3834 UINT *src_size, WCHAR *dest, UINT *dest_size)
3836 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3837 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3838 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3841 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3842 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3844 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3845 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3846 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3849 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3851 MLangConvertCharset_QueryInterface,
3852 MLangConvertCharset_AddRef,
3853 MLangConvertCharset_Release,
3854 MLangConvertCharset_Initialize,
3855 MLangConvertCharset_GetSourceCodePage,
3856 MLangConvertCharset_GetDestinationCodePage,
3857 MLangConvertCharset_GetProperty,
3858 MLangConvertCharset_DoConversion,
3859 MLangConvertCharset_DoConversionToUnicode,
3860 MLangConvertCharset_DoConversionFromUnicode
3863 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3865 MLang_impl *mlang;
3866 UINT i;
3868 TRACE("Creating MultiLanguage object\n");
3870 if( pUnkOuter )
3871 return CLASS_E_NOAGGREGATION;
3873 mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3874 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3875 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3876 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3877 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3878 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3880 mlang->total_cp = 0;
3881 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3882 mlang->total_cp += mlang_data[i].number_of_cp;
3884 /* do not enumerate unicode flavours */
3885 mlang->total_scripts = ARRAY_SIZE(mlang_data) - 1;
3887 mlang->ref = 1;
3888 *ppObj = &mlang->IMultiLanguage_iface;
3889 TRACE("returning %p\n", mlang);
3891 LockModule();
3893 return S_OK;
3896 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3898 struct convert_charset *convert;
3900 if (outer)
3901 return CLASS_E_NOAGGREGATION;
3903 *obj = NULL;
3905 convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3906 if (!convert) return E_OUTOFMEMORY;
3908 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3909 convert->ref = 1;
3911 *obj = &convert->IMLangConvertCharset_iface;
3913 LockModule();
3915 return S_OK;
3918 /******************************************************************************/
3920 HRESULT WINAPI DllCanUnloadNow(void)
3922 return dll_count == 0 ? S_OK : S_FALSE;
3925 static BOOL register_codepages(void)
3927 const struct mlang_data *family;
3928 const MIME_CP_INFO *info;
3929 HKEY db_key, key;
3930 WCHAR buf[32];
3931 LSTATUS status;
3933 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"MIME\\Database\\Codepage", &db_key);
3934 if (status != ERROR_SUCCESS)
3935 return FALSE;
3937 for (family = mlang_data; family < mlang_data + ARRAY_SIZE(mlang_data); family++)
3939 for (info = family->mime_cp_info; info < family->mime_cp_info + family->number_of_cp; info++)
3941 swprintf(buf, ARRAY_SIZE(buf), L"%u", info->cp);
3942 status = RegCreateKeyW(db_key, buf, &key);
3943 if (status != ERROR_SUCCESS)
3944 continue;
3946 RegSetValueExA(key, "BodyCharset", 0, REG_SZ, (BYTE*)info->body_charset,
3947 strlen(info->body_charset) + 1);
3949 if (info->cp == family->family_codepage)
3951 RegSetValueExA(key, "FixedWidthFont", 0, REG_SZ, (BYTE*)family->fixed_font,
3952 strlen(family->fixed_font) + 1);
3953 RegSetValueExA(key, "ProportionalFont", 0, REG_SZ, (BYTE*)family->proportional_font,
3954 strlen(family->proportional_font) + 1);
3956 else
3958 RegSetValueExW(key, L"Family", 0, REG_DWORD, (BYTE*)&family->family_codepage,
3959 sizeof(family->family_codepage));
3962 RegCloseKey(key);
3966 RegCloseKey(db_key);
3967 return TRUE;
3970 /***********************************************************************
3971 * DllRegisterServer (MLANG.@)
3973 HRESULT WINAPI DllRegisterServer(void)
3975 if(!register_codepages())
3976 return E_FAIL;
3977 return __wine_register_resources();
3980 /***********************************************************************
3981 * DllUnregisterServer (MLANG.@)
3983 HRESULT WINAPI DllUnregisterServer(void)
3985 return __wine_unregister_resources();
3988 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
3990 if (!unknown) return E_INVALIDARG;
3992 FIXME("%p: stub\n", unknown);
3994 return S_FALSE;