rasapi32: Update spec file.
[wine/zf.git] / dlls / mlang / mlang.c
blob62e9947fb73d5edea9ac96854e4afe1fca8341f2
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 HINSTANCE instance;
52 static DWORD MLANG_tls_index; /* to store various per thead data */
54 /* FIXME:
55 * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
56 * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
59 typedef struct
61 const char *description;
62 UINT cp;
63 DWORD flags;
64 const char *web_charset;
65 const char *header_charset;
66 const char *body_charset;
67 const WCHAR *alias;
68 } MIME_CP_INFO;
70 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
71 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
73 static const MIME_CP_INFO arabic_cp[] =
75 { "Arabic (864)",
76 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
77 MIMECONTF_MIME_LATEST,
78 "ibm864", "ibm864", "ibm864" },
79 { "Arabic (1006)",
80 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
81 MIMECONTF_MIME_LATEST,
82 "ibm1006", "ibm1006", "ibm1006" },
83 { "Arabic (Windows)",
84 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
85 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
86 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
87 "windows-1256", "windows-1256", "windows-1256" },
88 { "Arabic (ISO)",
89 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
90 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
91 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
92 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
93 "iso-8859-6", "iso-8859-6", "iso-8859-6" }
95 static const MIME_CP_INFO baltic_cp[] =
97 { "Baltic (DOS)",
98 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
99 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
100 "ibm775", "ibm775", "ibm775" },
101 { "Baltic (Windows)",
102 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
103 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
104 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
105 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
106 "windows-1257", "windows-1257", "windows-1257" },
107 { "Baltic (ISO)",
108 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
109 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
110 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
111 MIMECONTF_MIME_LATEST,
112 "iso-8859-4", "iso-8859-4", "iso-8859-4" },
113 { "Estonian (ISO)",
114 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
115 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
116 "iso-8859-13", "iso-8859-13", "iso-8859-13" }
118 static const MIME_CP_INFO chinese_simplified_cp[] =
120 { "Chinese Simplified (Auto-Select)",
121 50936, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
122 MIMECONTF_MIME_LATEST,
123 "_autodetect_chs", "_autodetect_chs", "_autodetect_chs" },
124 { "Chinese Simplified (GB2312)",
125 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
126 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
127 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
128 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
129 "gb2312", "gb2312", "gb2312" },
130 { "Chinese Simplified (GB2312-80)",
131 20936, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
132 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
133 "x-cp20936", "x-cp20936", "x-cp20936" },
134 { "Chinese Simplified (HZ)",
135 52936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
136 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
137 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
138 MIMECONTF_MIME_LATEST,
139 "hz-gb-2312", "hz-gb-2312", "hz-gb-2312" },
140 { "Chinese Simplified (GB18030)",
141 54936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
142 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
143 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
144 MIMECONTF_MIME_LATEST,
145 "GB18030", "GB18030", "GB18030" },
146 { "Chinese Simplified (GBK)",
147 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
148 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
149 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
150 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
151 "gbk", "gbk", "gbk" }
153 static const MIME_CP_INFO chinese_traditional_cp[] =
155 { "Chinese Traditional (Auto-Select)",
156 50950, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
157 MIMECONTF_MIME_LATEST,
158 "_autodetect_cht", "_autodetect_cht", "_autodetect_cht" },
159 { "Chinese Traditional (Big5)",
160 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
161 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
162 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
163 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
164 "big5", "big5", "big5" },
165 { "Chinese Traditional (CNS)",
166 20000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
167 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
168 "x-Chinese-CNS", "x-Chinese-CNS", "x-Chinese-CNS" }
170 static const MIME_CP_INFO central_european_cp[] =
172 { "Central European (DOS)",
173 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
174 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
175 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
176 "ibm852", "ibm852", "ibm852" },
177 { "Central European (Windows)",
178 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
179 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
180 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
181 MIMECONTF_MIME_LATEST,
182 "windows-1250", "windows-1250", "windows-1250" },
183 { "Central European (Mac)",
184 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
185 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
186 "x-mac-ce", "x-mac-ce", "x-mac-ce" },
187 { "Central European (ISO)",
188 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
189 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
190 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
191 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
192 "iso-8859-2", "iso-8859-2", "iso-8859-2" }
194 static const MIME_CP_INFO cyrillic_cp[] =
196 { "OEM Cyrillic",
197 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
198 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
199 "ibm855", "ibm855", "ibm855" },
200 { "Cyrillic (DOS)",
201 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
202 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
203 MIMECONTF_MIME_LATEST,
204 "cp866", "cp866", "cp866" },
205 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
206 { "Cyrillic (KOI8-R)",
207 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
208 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
209 "koi8-r", "koi8-r", "koi8-r" },
210 #endif
211 { "Cyrillic (Windows)",
212 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
213 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
214 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
215 "windows-1251", "windows-1251", "windows-1251" },
216 { "Cyrillic (Mac)",
217 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
218 MIMECONTF_MIME_LATEST,
219 "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
220 { "Cyrillic (KOI8-R)",
221 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
222 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
223 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
224 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
225 "koi8-r", "koi8-r", "koi8-r" },
226 { "Cyrillic (KOI8-U)",
227 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
228 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
229 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
230 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
231 "koi8-u", "koi8-u", "koi8-u" },
232 { "Cyrillic (ISO)",
233 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
234 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
235 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
236 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
237 "iso-8859-5", "iso-8859-5", "iso-8859-5" }
239 static const MIME_CP_INFO greek_cp[] =
241 { "Greek (DOS)",
242 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
243 MIMECONTF_MIME_LATEST,
244 "ibm737", "ibm737", "ibm737" },
245 { "Greek, Modern (DOS)",
246 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
247 MIMECONTF_MIME_LATEST,
248 "ibm869", "ibm869", "ibm869" },
249 { "IBM EBCDIC (Greek Modern)",
250 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
251 MIMECONTF_MIME_LATEST,
252 "cp875", "cp875", "cp875" },
253 { "Greek (Windows)",
254 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
255 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
256 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
257 "windows-1253", "windows-1253", "windows-1253" },
258 { "Greek (Mac)",
259 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
260 MIMECONTF_MIME_LATEST,
261 "x-mac-greek", "x-mac-greek", "x-mac-greek" },
262 { "Greek (ISO)",
263 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
264 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
265 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
266 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
267 "iso-8859-7", "iso-8859-7", "iso-8859-7" }
269 static const MIME_CP_INFO hebrew_cp[] =
271 { "Hebrew (424)",
272 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
273 MIMECONTF_MIME_LATEST,
274 "ibm424", "ibm424", "ibm424" },
275 { "Hebrew (856)",
276 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
277 MIMECONTF_MIME_LATEST,
278 "cp856", "cp856", "cp856" },
279 { "Hebrew (DOS)",
280 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
281 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
282 MIMECONTF_MIME_LATEST,
283 "dos-862", "dos-862", "dos-862" },
284 { "Hebrew (Windows)",
285 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
286 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
287 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
288 "windows-1255", "windows-1255", "windows-1255" },
289 { "Hebrew (ISO-Visual)",
290 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
291 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
292 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
293 "iso-8859-8", "iso-8859-8", "iso-8859-8" }
295 static const MIME_CP_INFO japanese_cp[] =
297 { "Japanese (Auto-Select)",
298 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
299 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
300 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
301 "_autodetect", "_autodetect", "_autodetect" },
302 { "Japanese (EUC)",
303 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
304 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
305 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
306 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
307 "euc-jp", "euc-jp", "euc-jp" },
308 { "Japanese (JIS)",
309 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
310 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
311 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
312 MIMECONTF_MIME_IE4,
313 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
314 { "Japanese (JIS 0208-1990 and 0212-1990)",
315 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
316 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
317 "EUC-JP","EUC-JP","EUC-JP"},
318 { "Japanese (JIS-Allow 1 byte Kana)",
319 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
320 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
321 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
322 "csISO2022JP","iso-2022-jp","iso-2022-jp"},
323 { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
324 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
325 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
326 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
327 { "Japanese (Mac)",
328 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
329 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
330 "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
331 { "Japanese (Shift-JIS)",
332 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
333 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
334 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
335 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
336 "shift_jis", "iso-2022-jp", "iso-2022-jp" }
338 static const MIME_CP_INFO korean_cp[] =
340 { "Korean",
341 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
342 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
343 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
344 MIMECONTF_MIME_LATEST,
345 "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
347 static const MIME_CP_INFO thai_cp[] =
349 { "Thai (Windows)",
350 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
351 "ibm-thai", "ibm-thai", "ibm-thai" }
353 static const MIME_CP_INFO turkish_cp[] =
355 { "Turkish (DOS)",
356 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
357 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
358 "ibm857", "ibm857", "ibm857" },
359 { "IBM EBCDIC (Turkish Latin-5)",
360 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
361 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
362 "ibm1026", "ibm1026", "ibm1026" },
363 { "Turkish (Windows)",
364 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
365 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
366 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
367 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
368 "windows-1254", "windows-1254", "windows-1254" },
369 { "Turkish (Mac)",
370 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
371 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
372 "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
373 { "Latin 3 (ISO)",
374 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
375 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
376 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
377 "iso-8859-3", "iso-8859-3", "iso-8859-3" },
378 { "Turkish (ISO)",
379 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
380 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
381 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
382 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
383 "iso-8859-9", "iso-8859-9", "iso-8859-9" }
385 static const MIME_CP_INFO vietnamese_cp[] =
387 { "Vietnamese (Windows)",
388 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
389 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
390 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
391 MIMECONTF_MIME_LATEST,
392 "windows-1258", "windows-1258", "windows-1258" }
395 static const MIME_CP_INFO western_cp[] =
397 { "IBM EBCDIC (US-Canada)",
398 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
399 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
400 "ibm037", "ibm037", "ibm037" },
401 { "OEM United States",
402 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
403 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
404 "ibm437", "ibm437", "ibm437" },
405 { "IBM EBCDIC (International)",
406 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
407 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
408 "ibm500", "ibm500", "ibm500" },
409 { "Western European (DOS)",
410 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
411 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
412 "ibm850", "ibm850", "ibm850" },
413 { "Portuguese (DOS)",
414 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
415 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
416 "ibm860", "ibm860", "ibm860" },
417 { "Icelandic (DOS)",
418 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
419 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
420 "ibm861", "ibm861", "ibm861" },
421 { "French Canadian (DOS)",
422 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
423 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
424 "ibm863", "ibm863", "ibm863" },
425 { "Nordic (DOS)",
426 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
427 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
428 "ibm865", "ibm865", "ibm865" },
429 { "Western European (Windows)",
430 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
431 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
432 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
433 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
434 "windows-1252", "windows-1252", "iso-8859-1" },
435 { "Western European (Mac)",
436 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
437 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
438 "macintosh", "macintosh", "macintosh" },
439 { "Icelandic (Mac)",
440 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
441 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
442 "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
443 { "US-ASCII",
444 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
445 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
446 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
447 "us-ascii", "us-ascii", "us-ascii", L"ascii" },
448 { "Western European (ISO)",
449 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
450 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
451 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
452 MIMECONTF_MIME_LATEST,
453 "iso-8859-1", "iso-8859-1", "iso-8859-1" },
454 { "Latin 9 (ISO)",
455 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
456 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
457 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
458 MIMECONTF_MIME_LATEST,
459 "iso-8859-15", "iso-8859-15", "iso-8859-15" }
461 static const MIME_CP_INFO unicode_cp[] =
463 { "Unicode",
464 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
465 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
466 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
467 MIMECONTF_MIME_LATEST,
468 "unicode", "unicode", "unicode" },
469 { "Unicode (UTF-7)",
470 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
471 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
472 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
473 "utf-7", "utf-7", "utf-7" },
474 { "Unicode (UTF-8)",
475 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
476 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
477 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
478 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
479 "utf-8", "utf-8", "utf-8" }
482 static const struct mlang_data
484 const char *description;
485 UINT family_codepage;
486 UINT number_of_cp;
487 const MIME_CP_INFO *mime_cp_info;
488 const char *fixed_font;
489 const char *proportional_font;
490 SCRIPT_ID sid;
491 } mlang_data[] =
493 { "Arabic", 1256, ARRAY_SIZE(arabic_cp), arabic_cp,
494 "Simplified Arabic Fixed","Simplified Arabic", sidArabic },
495 { "Baltic", 1257, ARRAY_SIZE(baltic_cp), baltic_cp,
496 "Courier New","Arial", sidAsciiLatin },
497 { "Chinese Simplified", 936, ARRAY_SIZE(chinese_simplified_cp), chinese_simplified_cp,
498 "Simsun","Simsun", sidHan },
499 { "Chinese Traditional", 950, ARRAY_SIZE(chinese_traditional_cp), chinese_traditional_cp,
500 "MingLiu","New MingLiu", sidBopomofo },
501 { "Central European", 1250, ARRAY_SIZE(central_european_cp), central_european_cp,
502 "Courier New","Arial", sidAsciiLatin },
503 { "Cyrillic", 1251, ARRAY_SIZE(cyrillic_cp), cyrillic_cp,
504 "Courier New","Arial", sidCyrillic },
505 { "Greek", 1253, ARRAY_SIZE(greek_cp), greek_cp,
506 "Courier New","Arial", sidGreek },
507 { "Hebrew", 1255, ARRAY_SIZE(hebrew_cp), hebrew_cp,
508 "Miriam Fixed","David", sidHebrew },
509 { "Japanese", 932, ARRAY_SIZE(japanese_cp), japanese_cp,
510 "MS Gothic","MS PGothic", sidKana },
511 { "Korean", 949, ARRAY_SIZE(korean_cp), korean_cp,
512 "GulimChe","Gulim", sidHangul },
513 { "Thai", 874, ARRAY_SIZE(thai_cp), thai_cp,
514 "Tahoma","Tahoma", sidThai },
515 { "Turkish", 1254, ARRAY_SIZE(turkish_cp), turkish_cp,
516 "Courier New","Arial", sidAsciiLatin },
517 { "Vietnamese", 1258, ARRAY_SIZE(vietnamese_cp), vietnamese_cp,
518 "Courier New","Arial", sidAsciiLatin },
519 { "Western European", 1252, ARRAY_SIZE(western_cp), western_cp,
520 "Courier New","Arial", sidAsciiLatin },
521 { "Unicode", CP_UNICODE, ARRAY_SIZE(unicode_cp), unicode_cp,
522 "Courier New","Arial" }
525 struct font_list
527 struct list list_entry;
528 HFONT base_font;
529 HFONT font;
530 UINT charset;
533 static struct list font_cache = LIST_INIT(font_cache);
534 static CRITICAL_SECTION font_cache_critical;
535 static CRITICAL_SECTION_DEBUG font_cache_critical_debug =
537 0, 0, &font_cache_critical,
538 { &font_cache_critical_debug.ProcessLocksList, &font_cache_critical_debug.ProcessLocksList },
539 0, 0, { (DWORD_PTR)(__FILE__ ": font_cache_critical") }
541 static CRITICAL_SECTION font_cache_critical = { &font_cache_critical_debug, -1, 0, 0, 0, 0 };
543 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
545 static LONG dll_count;
548 * Japanese Detection and Conversion Functions
551 #define HANKATA(A) ((A >= 161) && (A <= 223))
552 #define ISEUC(A) ((A >= 161) && (A <= 254))
553 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
554 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
555 #define SJIS2(A) ((A >= 64) && (A <= 252))
556 #define ISMARU(A) ((A >= 202) && (A <= 206))
557 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
559 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
561 UINT code = 0;
562 DWORD i = 0;
563 unsigned char c1,c2;
565 while ((code == 0 || code == 51932) && i < count)
567 c1 = input[i];
568 if (c1 == 0x1b /* ESC */)
570 i++;
571 if (i >= count)
572 return code;
573 c1 = input[i];
574 if (c1 == '$')
576 i++;
577 if (i >= count)
578 return code;
579 c1 = input[i];
580 if (c1 =='B' || c1 == '@')
581 code = 50220;
583 if (c1 == 'K')
584 code = 50220;
586 else if (c1 >= 129)
588 i++;
589 if (i >= count)
590 return code;
591 c2 = input[i];
592 if NOTEUC(c1,c2)
593 code = 932;
594 else if (ISEUC(c1) && ISEUC(c2))
595 code = 51932;
596 else if (((c1 == 142)) && HANKATA(c2))
597 code = 51932;
599 i++;
601 return code;
604 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
606 unsigned char c1 = *p1;
607 unsigned char c2 = *p2;
608 int row = c1 < 95 ? 112 : 176;
609 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
611 *p1 = ((c1 + 1) >> 1) + row;
612 *p2 = c2 + cell;
615 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
617 unsigned char c1 = *p1;
618 unsigned char c2 = *p2;
619 int shift = c2 < 159;
620 int row = c1 < 160 ? 112 : 176;
621 int cell = shift ? (31 + (c2 > 127)): 126;
623 *p1 = ((c1 - row) << 1) - shift;
624 *p2 -= cell;
627 static int han2zen(unsigned char *p1, unsigned char *p2)
629 BOOL maru = FALSE;
630 BOOL nigori = FALSE;
631 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
632 131,131,131,131,131,131,129,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,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
635 131,129,129 };
636 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
637 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
638 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
639 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
641 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
642 nigori = TRUE;
643 else if ((*p2 == 223) && (ISMARU(*p1)))
644 maru = TRUE;
646 if (*p1 >= 161 && *p1 <= 223)
648 unsigned char index = *p1 - 161;
649 *p1 = char1[index];
650 *p2 = char2[index];
653 if (maru || nigori)
655 if (nigori)
657 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
658 (*p2)++;
659 else if ((*p1 == 131) && (*p2 == 69))
660 *p2 = 148;
662 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
663 *p2+= 2;
665 return 1;
668 return 0;
672 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
674 DWORD i = 0;
675 int j = 0;
676 unsigned char p2,p;
677 BOOL shifted = FALSE;
679 while (i < count)
681 p = input[i];
682 if (p == 0x1b /* ESC */)
684 i++;
685 if (i >= count)
686 return 0;
687 p2 = input[i];
688 if (p2 == '$' || p2 =='(')
689 i++;
690 if (p2 == 'K' || p2 =='$')
691 shifted = TRUE;
692 else
693 shifted = FALSE;
695 else
697 if (shifted)
699 i++;
700 if (i >= count)
701 return 0;
702 p2 = input[i];
703 jis2sjis(&p,&p2);
704 output[j++]=p;
705 output[j++]=p2;
707 else
709 output[j++] = p;
712 i++;
714 return j;
717 static inline int exit_shift(LPSTR out, int c)
719 if (out)
721 out[c] = 0x1b;
722 out[c+1] = '(';
723 out[c+2] = 'B';
725 return 3;
728 static inline int enter_shift(LPSTR out, int c)
730 if (out)
732 out[c] = 0x1b;
733 out[c+1] = '$';
734 out[c+2] = 'B';
736 return 3;
740 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
742 DWORD i = 0;
743 int j = 0;
744 unsigned char p2,p;
745 BOOL shifted = FALSE;
747 while (i < count)
749 p = input[i] & 0xff;
750 if (p == 10 || p == 13) /* NL and CR */
752 if (shifted)
754 shifted = FALSE;
755 j += exit_shift(output,j);
757 if (output)
758 output[j++] = p;
759 else
760 j++;
762 else
764 if (SJIS1(p))
766 i++;
767 if (i >= count)
768 return 0;
769 p2 = input[i] & 0xff;
770 if (SJIS2(p2))
772 sjis2jis(&p,&p2);
773 if (!shifted)
775 shifted = TRUE;
776 j+=enter_shift(output,j);
780 if (output)
782 output[j++]=p;
783 output[j++]=p2;
785 else
786 j+=2;
788 else
790 if (HANKATA(p))
792 if ((i+1) >= count)
793 return 0;
794 p2 = input[i+1] & 0xff;
795 i+=han2zen(&p,&p2);
796 sjis2jis(&p,&p2);
797 if (!shifted)
799 shifted = TRUE;
800 j+=enter_shift(output,j);
802 if (output)
804 output[j++]=p;
805 output[j++]=p2;
807 else
808 j+=2;
810 else
812 if (shifted)
814 shifted = FALSE;
815 j += exit_shift(output,j);
817 if (output)
818 output[j++]=p;
819 else
820 j++;
824 i++;
826 if (shifted)
827 j += exit_shift(output,j);
828 return j;
831 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
832 LPWSTR output, DWORD out_count)
834 CHAR *sjis_string;
835 UINT rc = 0;
836 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
837 rc = ConvertJIS2SJIS(input,count,sjis_string);
838 if (rc)
840 TRACE("%s\n",debugstr_an(sjis_string,rc));
841 if (output)
842 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
843 else
844 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
846 HeapFree(GetProcessHeap(),0,sjis_string);
847 return rc;
851 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
852 LPWSTR output, DWORD out_count)
854 CHAR *sjis_string;
855 UINT rc = 0;
856 int code = DetectJapaneseCode(input,count);
857 TRACE("Japanese code %i\n",code);
859 switch (code)
861 case 0:
862 if (output)
863 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
864 else
865 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
866 break;
868 case 932:
869 if (output)
870 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
871 else
872 rc = MultiByteToWideChar(932,0,input,count,0,0);
873 break;
875 case 51932:
876 if (output)
877 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
878 else
879 rc = MultiByteToWideChar(20932,0,input,count,0,0);
880 break;
882 case 50220:
883 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
884 rc = ConvertJIS2SJIS(input,count,sjis_string);
885 if (rc)
887 TRACE("%s\n",debugstr_an(sjis_string,rc));
888 if (output)
889 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
890 else
891 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
893 HeapFree(GetProcessHeap(),0,sjis_string);
894 break;
896 return rc;
899 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
900 LPSTR output, DWORD out_count)
902 CHAR *sjis_string;
903 INT len;
904 UINT rc = 0;
906 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
907 sjis_string = HeapAlloc(GetProcessHeap(),0,len);
908 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
909 TRACE("%s\n",debugstr_an(sjis_string,len));
911 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
912 if (out_count >= rc)
914 ConvertSJIS2JIS(sjis_string, len, output);
916 HeapFree(GetProcessHeap(),0,sjis_string);
917 return rc;
922 * Dll lifetime tracking declaration
924 static void LockModule(void)
926 InterlockedIncrement(&dll_count);
929 static void UnlockModule(void)
931 InterlockedDecrement(&dll_count);
934 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
936 switch(fdwReason) {
937 case DLL_PROCESS_ATTACH:
938 instance = hInstDLL;
939 MLANG_tls_index = TlsAlloc();
940 DisableThreadLibraryCalls(hInstDLL);
941 break;
942 case DLL_PROCESS_DETACH:
943 if (lpv) break;
944 TlsFree(MLANG_tls_index);
945 break;
947 return TRUE;
950 HRESULT WINAPI ConvertINetMultiByteToUnicode(
951 LPDWORD pdwMode,
952 DWORD dwEncoding,
953 LPCSTR pSrcStr,
954 LPINT pcSrcSize,
955 LPWSTR pDstStr,
956 LPINT pcDstSize)
958 INT src_len = -1;
960 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
961 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
963 if (!pcDstSize)
964 return E_FAIL;
966 if (!pcSrcSize)
967 pcSrcSize = &src_len;
969 if (!*pcSrcSize)
971 *pcDstSize = 0;
972 return S_OK;
975 /* forwarding euc-jp to EUC-JP */
976 if (dwEncoding == 51932)
977 dwEncoding = 20932;
979 switch (dwEncoding)
981 case CP_UNICODE:
982 if (*pcSrcSize == -1)
983 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
984 *pcDstSize = min(*pcSrcSize, *pcDstSize);
985 *pcSrcSize *= sizeof(WCHAR);
986 if (pDstStr)
987 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
988 break;
990 case 50220:
991 case 50221:
992 case 50222:
993 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
994 break;
995 case 50932:
996 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
997 break;
999 default:
1000 if (*pcSrcSize == -1)
1001 *pcSrcSize = lstrlenA(pSrcStr);
1003 if (pDstStr)
1004 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
1005 else
1006 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
1007 break;
1010 if (!*pcDstSize)
1011 return E_FAIL;
1013 return S_OK;
1016 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
1017 LPDWORD pdwMode,
1018 DWORD dwEncoding,
1019 LPCWSTR pSrcStr,
1020 LPINT pcSrcSize,
1021 LPSTR pDstStr,
1022 LPINT pcDstSize)
1024 INT destsz, size;
1025 INT src_len = -1;
1027 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
1028 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1030 if (!pcDstSize)
1031 return S_OK;
1033 if (!pcSrcSize)
1034 pcSrcSize = &src_len;
1036 destsz = (pDstStr) ? *pcDstSize : 0;
1037 *pcDstSize = 0;
1039 if (!pSrcStr || !*pcSrcSize)
1040 return S_OK;
1042 if (*pcSrcSize == -1)
1043 *pcSrcSize = lstrlenW(pSrcStr);
1045 /* forwarding euc-jp to EUC-JP */
1046 if (dwEncoding == 51932)
1047 dwEncoding = 20932;
1049 if (dwEncoding == CP_UNICODE)
1051 if (*pcSrcSize == -1)
1052 *pcSrcSize = lstrlenW(pSrcStr);
1054 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1055 if (pDstStr)
1056 memmove(pDstStr, pSrcStr, size);
1058 if (size >= destsz)
1059 goto fail;
1061 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1063 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1064 if (!size)
1065 goto fail;
1067 if (pDstStr)
1069 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1070 destsz);
1071 if (!size)
1072 goto fail;
1076 else
1078 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1079 NULL, 0, NULL, NULL);
1080 if (!size)
1081 goto fail;
1083 if (pDstStr)
1085 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1086 pDstStr, destsz, NULL, NULL);
1087 if (!size)
1088 goto fail;
1092 *pcDstSize = size;
1093 return S_OK;
1095 fail:
1096 *pcSrcSize = 0;
1097 *pcDstSize = 0;
1098 return E_FAIL;
1101 HRESULT WINAPI ConvertINetString(
1102 LPDWORD pdwMode,
1103 DWORD dwSrcEncoding,
1104 DWORD dwDstEncoding,
1105 LPCSTR pSrcStr,
1106 LPINT pcSrcSize,
1107 LPSTR pDstStr,
1108 LPINT pcDstSize
1111 TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1112 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1114 if (dwSrcEncoding == CP_UNICODE)
1116 INT cSrcSizeW;
1117 if (pcSrcSize && *pcSrcSize != -1)
1119 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1120 pcSrcSize = &cSrcSizeW;
1122 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1124 else if (dwDstEncoding == CP_UNICODE)
1126 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1127 *pcDstSize *= sizeof(WCHAR);
1128 return hr;
1130 else
1132 INT cDstSizeW;
1133 LPWSTR pDstStrW;
1134 HRESULT hr;
1136 TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1138 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1139 if (hr != S_OK)
1140 return hr;
1142 pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1143 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1144 if (hr == S_OK)
1145 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1147 HeapFree(GetProcessHeap(), 0, pDstStrW);
1148 return hr;
1152 static HRESULT GetFamilyCodePage(
1153 UINT uiCodePage,
1154 UINT* puiFamilyCodePage)
1156 UINT i, n;
1158 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1160 if (!puiFamilyCodePage) return S_FALSE;
1162 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1164 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1166 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1168 *puiFamilyCodePage = mlang_data[i].family_codepage;
1169 return S_OK;
1174 return S_FALSE;
1177 HRESULT WINAPI IsConvertINetStringAvailable(
1178 DWORD dwSrcEncoding,
1179 DWORD dwDstEncoding)
1181 UINT src_family, dst_family;
1183 TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
1185 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1186 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1187 return S_FALSE;
1189 if (src_family == dst_family) return S_OK;
1191 /* we can convert any codepage to/from unicode */
1192 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1194 return S_FALSE;
1197 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1199 CHAR buffer[MAX_RFC1766_NAME];
1200 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1201 INT i;
1203 if (n)
1205 i = PRIMARYLANGID(lcid);
1206 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1207 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1208 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1210 buffer[n - 1] = '-';
1211 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1212 if (!i)
1213 buffer[n - 1] = '\0';
1215 else
1216 i = 0;
1218 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1219 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1221 return E_FAIL;
1224 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1226 WCHAR buffer[MAX_RFC1766_NAME];
1227 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1228 INT i;
1230 if (n)
1232 i = PRIMARYLANGID(lcid);
1233 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1234 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1235 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1237 buffer[n - 1] = '-';
1238 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1239 if (!i)
1240 buffer[n - 1] = '\0';
1242 else
1243 i = 0;
1245 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1246 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1248 return E_FAIL;
1251 HRESULT WINAPI LcidToRfc1766A(
1252 LCID lcid,
1253 LPSTR pszRfc1766,
1254 INT nChar)
1256 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1257 if (!pszRfc1766)
1258 return E_INVALIDARG;
1260 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1263 HRESULT WINAPI LcidToRfc1766W(
1264 LCID lcid,
1265 LPWSTR pszRfc1766,
1266 INT nChar)
1268 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1269 if (!pszRfc1766)
1270 return E_INVALIDARG;
1272 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1275 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1277 RFC1766INFO info;
1278 ULONG num;
1280 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1282 if (!wcsicmp(info.wszRfc1766, rfc1766))
1284 *lcid = info.lcid;
1285 return S_OK;
1287 if (lstrlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1289 *lcid = PRIMARYLANGID(info.lcid);
1290 return S_OK;
1294 return E_FAIL;
1297 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1299 IEnumRfc1766 *enumrfc1766;
1300 HRESULT hr;
1302 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1304 if (!pLocale || !pszRfc1766)
1305 return E_INVALIDARG;
1307 hr = EnumRfc1766_create(0, &enumrfc1766);
1308 if (FAILED(hr))
1309 return hr;
1311 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1312 IEnumRfc1766_Release(enumrfc1766);
1314 return hr;
1317 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1319 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1321 if (!rfc1766A)
1322 return E_INVALIDARG;
1324 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1325 rfc1766W[MAX_RFC1766_NAME] = 0;
1327 return Rfc1766ToLcidW(lcid, rfc1766W);
1330 static HRESULT map_font(HDC hdc, DWORD codepages, HFONT src_font, HFONT *dst_font)
1332 struct font_list *font_list_entry;
1333 CHARSETINFO charset_info;
1334 HFONT new_font, old_font;
1335 LOGFONTW font_attr;
1336 DWORD mask, Csb[2];
1337 BOOL found_cached;
1338 UINT charset;
1339 BOOL ret;
1340 UINT i;
1342 if (hdc == NULL || src_font == NULL) return E_FAIL;
1344 for (i = 0; i < 32; i++)
1346 mask = (DWORD)(1 << i);
1347 if (codepages & mask)
1349 Csb[0] = mask;
1350 Csb[1] = 0x0;
1351 ret = TranslateCharsetInfo(Csb, &charset_info, TCI_SRCFONTSIG);
1352 if (!ret) continue;
1354 /* use cached font if possible */
1355 found_cached = FALSE;
1356 EnterCriticalSection(&font_cache_critical);
1357 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1359 if (font_list_entry->charset == charset_info.ciCharset &&
1360 font_list_entry->base_font == src_font)
1362 if (dst_font != NULL)
1363 *dst_font = font_list_entry->font;
1364 found_cached = TRUE;
1367 LeaveCriticalSection(&font_cache_critical);
1368 if (found_cached) return S_OK;
1370 GetObjectW(src_font, sizeof(font_attr), &font_attr);
1371 font_attr.lfCharSet = (BYTE)charset_info.ciCharset;
1372 font_attr.lfWidth = 0;
1373 font_attr.lfFaceName[0] = 0;
1374 new_font = CreateFontIndirectW(&font_attr);
1375 if (new_font == NULL) continue;
1377 old_font = SelectObject(hdc, new_font);
1378 charset = GetTextCharset(hdc);
1379 SelectObject(hdc, old_font);
1380 if (charset == charset_info.ciCharset)
1382 font_list_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_list_entry));
1383 if (font_list_entry == NULL) return E_OUTOFMEMORY;
1385 font_list_entry->base_font = src_font;
1386 font_list_entry->font = new_font;
1387 font_list_entry->charset = charset;
1389 EnterCriticalSection(&font_cache_critical);
1390 list_add_tail(&font_cache, &font_list_entry->list_entry);
1391 LeaveCriticalSection(&font_cache_critical);
1393 if (dst_font != NULL)
1394 *dst_font = new_font;
1395 return S_OK;
1400 return E_FAIL;
1403 static HRESULT release_font(HFONT font)
1405 struct font_list *font_list_entry;
1406 HRESULT hr;
1408 hr = E_FAIL;
1409 EnterCriticalSection(&font_cache_critical);
1410 LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
1412 if (font_list_entry->font == font)
1414 list_remove(&font_list_entry->list_entry);
1415 DeleteObject(font);
1416 HeapFree(GetProcessHeap(), 0, font_list_entry);
1417 hr = S_OK;
1418 break;
1421 LeaveCriticalSection(&font_cache_critical);
1423 return hr;
1426 static HRESULT clear_font_cache(void)
1428 struct font_list *font_list_entry;
1429 struct font_list *font_list_entry2;
1431 EnterCriticalSection(&font_cache_critical);
1432 LIST_FOR_EACH_ENTRY_SAFE(font_list_entry, font_list_entry2, &font_cache, struct font_list, list_entry)
1434 list_remove(&font_list_entry->list_entry);
1435 DeleteObject(font_list_entry->font);
1436 HeapFree(GetProcessHeap(), 0, font_list_entry);
1438 LeaveCriticalSection(&font_cache_critical);
1440 return S_OK;
1443 /******************************************************************************
1444 * MLANG ClassFactory
1446 typedef struct {
1447 IClassFactory IClassFactory_iface;
1448 LONG ref;
1449 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1450 } IClassFactoryImpl;
1452 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1454 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1457 struct object_creation_info
1459 const CLSID *clsid;
1460 LPCSTR szClassName;
1461 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1464 static const struct object_creation_info object_creation[] =
1466 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1467 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1470 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1472 TRACE("%s\n", debugstr_guid(riid) );
1474 if (IsEqualGUID(riid, &IID_IUnknown)
1475 || IsEqualGUID(riid, &IID_IClassFactory))
1477 IClassFactory_AddRef(iface);
1478 *ppobj = iface;
1479 return S_OK;
1482 *ppobj = NULL;
1483 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1484 return E_NOINTERFACE;
1487 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1489 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1490 return InterlockedIncrement(&This->ref);
1493 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1495 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1496 ULONG ref = InterlockedDecrement(&This->ref);
1498 if (ref == 0)
1500 TRACE("Destroying %p\n", This);
1501 HeapFree(GetProcessHeap(), 0, This);
1504 return ref;
1507 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1508 REFIID riid, void **ppobj)
1510 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1511 HRESULT hres;
1512 LPUNKNOWN punk;
1514 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1516 *ppobj = NULL;
1517 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1518 if (SUCCEEDED(hres)) {
1519 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1520 IUnknown_Release(punk);
1522 TRACE("returning (%p) -> %x\n", *ppobj, hres);
1523 return hres;
1526 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1528 if (dolock)
1529 LockModule();
1530 else
1531 UnlockModule();
1533 return S_OK;
1536 static const IClassFactoryVtbl MLANGCF_Vtbl =
1538 MLANGCF_QueryInterface,
1539 MLANGCF_AddRef,
1540 MLANGCF_Release,
1541 MLANGCF_CreateInstance,
1542 MLANGCF_LockServer
1545 /******************************************************************
1546 * DllGetClassObject (MLANG.@)
1548 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1550 unsigned int i;
1551 IClassFactoryImpl *factory;
1553 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1555 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1556 && ! IsEqualGUID( &IID_IUnknown, iid) )
1557 return E_NOINTERFACE;
1559 for (i = 0; i < ARRAY_SIZE(object_creation); i++)
1561 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1562 break;
1565 if (i == ARRAY_SIZE(object_creation))
1567 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1568 return CLASS_E_CLASSNOTAVAILABLE;
1571 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1573 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1574 if (factory == NULL) return E_OUTOFMEMORY;
1576 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1577 factory->ref = 1;
1579 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1581 *ppv = &factory->IClassFactory_iface;
1583 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1585 return S_OK;
1589 /******************************************************************************/
1591 typedef struct tagMLang_impl
1593 IMLangFontLink IMLangFontLink_iface;
1594 IMultiLanguage IMultiLanguage_iface;
1595 IMultiLanguage3 IMultiLanguage3_iface;
1596 IMLangFontLink2 IMLangFontLink2_iface;
1597 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1598 LONG ref;
1599 DWORD total_cp, total_scripts;
1600 } MLang_impl;
1602 /******************************************************************************/
1604 typedef struct tagEnumCodePage_impl
1606 IEnumCodePage IEnumCodePage_iface;
1607 LONG ref;
1608 MIMECPINFO *cpinfo;
1609 DWORD total, pos;
1610 } EnumCodePage_impl;
1612 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1614 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1617 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1618 IEnumCodePage* iface,
1619 REFIID riid,
1620 void** ppvObject)
1622 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1624 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1626 if (IsEqualGUID(riid, &IID_IUnknown)
1627 || IsEqualGUID(riid, &IID_IEnumCodePage))
1629 IEnumCodePage_AddRef(iface);
1630 TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
1631 *ppvObject = &This->IEnumCodePage_iface;
1632 return S_OK;
1635 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1636 return E_NOINTERFACE;
1639 static ULONG WINAPI fnIEnumCodePage_AddRef(
1640 IEnumCodePage* iface)
1642 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1643 return InterlockedIncrement(&This->ref);
1646 static ULONG WINAPI fnIEnumCodePage_Release(
1647 IEnumCodePage* iface)
1649 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1650 ULONG ref = InterlockedDecrement(&This->ref);
1652 TRACE("%p ref = %d\n", This, ref);
1653 if (ref == 0)
1655 TRACE("Destroying %p\n", This);
1656 HeapFree(GetProcessHeap(), 0, This->cpinfo);
1657 HeapFree(GetProcessHeap(), 0, This);
1660 return ref;
1663 static HRESULT WINAPI fnIEnumCodePage_Clone(
1664 IEnumCodePage* iface,
1665 IEnumCodePage** ppEnum)
1667 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1668 FIXME("%p %p\n", This, ppEnum);
1669 return E_NOTIMPL;
1672 static HRESULT WINAPI fnIEnumCodePage_Next(
1673 IEnumCodePage* iface,
1674 ULONG celt,
1675 PMIMECPINFO rgelt,
1676 ULONG* pceltFetched)
1678 ULONG i;
1679 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1681 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1683 if (!pceltFetched) return S_FALSE;
1684 *pceltFetched = 0;
1686 if (!rgelt) return S_FALSE;
1688 if (This->pos + celt > This->total)
1689 celt = This->total - This->pos;
1691 if (!celt) return S_FALSE;
1693 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1694 *pceltFetched = celt;
1695 This->pos += celt;
1697 for (i = 0; i < celt; i++)
1699 TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
1700 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1701 rgelt[i].uiFamilyCodePage,
1702 wine_dbgstr_w(rgelt[i].wszDescription),
1703 wine_dbgstr_w(rgelt[i].wszWebCharset),
1704 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1705 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1706 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1707 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1708 rgelt[i].bGDICharset);
1710 return S_OK;
1713 static HRESULT WINAPI fnIEnumCodePage_Reset(
1714 IEnumCodePage* iface)
1716 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1718 TRACE("%p\n", This);
1720 This->pos = 0;
1721 return S_OK;
1724 static HRESULT WINAPI fnIEnumCodePage_Skip(
1725 IEnumCodePage* iface,
1726 ULONG celt)
1728 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1730 TRACE("%p %u\n", This, celt);
1732 if (celt >= This->total) return S_FALSE;
1734 This->pos += celt;
1735 return S_OK;
1738 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1740 fnIEnumCodePage_QueryInterface,
1741 fnIEnumCodePage_AddRef,
1742 fnIEnumCodePage_Release,
1743 fnIEnumCodePage_Clone,
1744 fnIEnumCodePage_Next,
1745 fnIEnumCodePage_Reset,
1746 fnIEnumCodePage_Skip
1749 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1750 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1752 EnumCodePage_impl *ecp;
1753 MIMECPINFO *cpinfo;
1754 UINT i, n;
1756 TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1758 if (!grfFlags) /* enumerate internal data base of encodings */
1759 grfFlags = MIMECONTF_MIME_LATEST;
1761 ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1762 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1763 ecp->ref = 1;
1764 ecp->pos = 0;
1765 ecp->total = 0;
1766 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1768 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1770 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1771 ecp->total++;
1775 ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1776 sizeof(MIMECPINFO) * ecp->total);
1777 cpinfo = ecp->cpinfo;
1779 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
1781 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1783 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1784 fill_cp_info(&mlang_data[i], n, cpinfo++);
1788 TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
1790 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1792 return S_OK;
1795 /******************************************************************************/
1797 typedef struct tagEnumScript_impl
1799 IEnumScript IEnumScript_iface;
1800 LONG ref;
1801 SCRIPTINFO *script_info;
1802 DWORD total, pos;
1803 } EnumScript_impl;
1805 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1807 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1810 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1811 IEnumScript* iface,
1812 REFIID riid,
1813 void** ppvObject)
1815 EnumScript_impl *This = impl_from_IEnumScript( iface );
1817 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1819 if (IsEqualGUID(riid, &IID_IUnknown)
1820 || IsEqualGUID(riid, &IID_IEnumScript))
1822 IEnumScript_AddRef(iface);
1823 TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
1824 *ppvObject = &This->IEnumScript_iface;
1825 return S_OK;
1828 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1829 return E_NOINTERFACE;
1832 static ULONG WINAPI fnIEnumScript_AddRef(
1833 IEnumScript* iface)
1835 EnumScript_impl *This = impl_from_IEnumScript( iface );
1836 return InterlockedIncrement(&This->ref);
1839 static ULONG WINAPI fnIEnumScript_Release(
1840 IEnumScript* iface)
1842 EnumScript_impl *This = impl_from_IEnumScript( iface );
1843 ULONG ref = InterlockedDecrement(&This->ref);
1845 TRACE("%p ref = %d\n", This, ref);
1846 if (ref == 0)
1848 TRACE("Destroying %p\n", This);
1849 HeapFree(GetProcessHeap(), 0, This->script_info);
1850 HeapFree(GetProcessHeap(), 0, This);
1853 return ref;
1856 static HRESULT WINAPI fnIEnumScript_Clone(
1857 IEnumScript* iface,
1858 IEnumScript** ppEnum)
1860 EnumScript_impl *This = impl_from_IEnumScript( iface );
1861 FIXME("%p %p: stub!\n", This, ppEnum);
1862 return E_NOTIMPL;
1865 static HRESULT WINAPI fnIEnumScript_Next(
1866 IEnumScript* iface,
1867 ULONG celt,
1868 PSCRIPTINFO rgelt,
1869 ULONG* pceltFetched)
1871 EnumScript_impl *This = impl_from_IEnumScript( iface );
1873 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1875 if (!pceltFetched || !rgelt) return E_FAIL;
1877 *pceltFetched = 0;
1879 if (This->pos + celt > This->total)
1880 celt = This->total - This->pos;
1882 if (!celt) return S_FALSE;
1884 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1885 *pceltFetched = celt;
1886 This->pos += celt;
1888 return S_OK;
1891 static HRESULT WINAPI fnIEnumScript_Reset(
1892 IEnumScript* iface)
1894 EnumScript_impl *This = impl_from_IEnumScript( iface );
1896 TRACE("%p\n", This);
1898 This->pos = 0;
1899 return S_OK;
1902 static HRESULT WINAPI fnIEnumScript_Skip(
1903 IEnumScript* iface,
1904 ULONG celt)
1906 EnumScript_impl *This = impl_from_IEnumScript( iface );
1908 TRACE("%p %u\n", This, celt);
1910 if (celt >= This->total) return S_FALSE;
1912 This->pos += celt;
1913 return S_OK;
1916 static const IEnumScriptVtbl IEnumScript_vtbl =
1918 fnIEnumScript_QueryInterface,
1919 fnIEnumScript_AddRef,
1920 fnIEnumScript_Release,
1921 fnIEnumScript_Clone,
1922 fnIEnumScript_Next,
1923 fnIEnumScript_Reset,
1924 fnIEnumScript_Skip
1927 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1928 LANGID LangId, IEnumScript** ppEnumScript )
1930 EnumScript_impl *es;
1931 UINT i;
1933 TRACE("%p, %08x, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1935 if (!dwFlags) /* enumerate all available scripts */
1936 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1938 es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1939 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1940 es->ref = 1;
1941 es->pos = 0;
1942 /* do not enumerate unicode flavours */
1943 es->total = ARRAY_SIZE(mlang_data) - 1;
1944 es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1946 for (i = 0; i < es->total; i++)
1948 es->script_info[i].ScriptId = i;
1949 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1950 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1951 es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1952 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1953 es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1954 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1955 es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1958 TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
1960 *ppEnumScript = &es->IEnumScript_iface;
1962 return S_OK;
1965 /******************************************************************************/
1967 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1969 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1972 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1973 IMLangFontLink* iface,
1974 REFIID riid,
1975 void** ppvObject)
1977 MLang_impl *This = impl_from_IMLangFontLink( iface );
1978 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1981 static ULONG WINAPI fnIMLangFontLink_AddRef(
1982 IMLangFontLink* iface)
1984 MLang_impl *This = impl_from_IMLangFontLink( iface );
1985 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1988 static ULONG WINAPI fnIMLangFontLink_Release(
1989 IMLangFontLink* iface)
1991 MLang_impl *This = impl_from_IMLangFontLink( iface );
1992 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1995 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1996 IMLangFontLink* iface,
1997 WCHAR ch_src,
1998 DWORD* codepages)
2000 MLang_impl *This = impl_from_IMLangFontLink( iface );
2001 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
2004 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
2005 IMLangFontLink* iface,
2006 const WCHAR* src,
2007 LONG src_len,
2008 DWORD priority_cp,
2009 DWORD* codepages,
2010 LONG* ret_len)
2012 MLang_impl *This = impl_from_IMLangFontLink( iface );
2013 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
2014 codepages, ret_len);
2017 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
2018 IMLangFontLink* iface,
2019 UINT codepage,
2020 DWORD* codepages)
2022 MLang_impl *This = impl_from_IMLangFontLink( iface );
2023 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
2026 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
2027 IMLangFontLink* iface,
2028 DWORD codepages,
2029 UINT def_codepage,
2030 UINT* codepage)
2032 MLang_impl *This = impl_from_IMLangFontLink(iface);
2033 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
2034 def_codepage, codepage);
2037 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
2038 IMLangFontLink* iface,
2039 HDC hdc,
2040 HFONT hfont,
2041 DWORD* codepages)
2043 MLang_impl *This = impl_from_IMLangFontLink(iface);
2044 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
2047 static HRESULT WINAPI fnIMLangFontLink_MapFont(
2048 IMLangFontLink* iface,
2049 HDC hDC,
2050 DWORD dwCodePages,
2051 HFONT hSrcFont,
2052 HFONT* phDestFont)
2054 TRACE("(%p)->%p %08x %p %p\n",iface, hDC, dwCodePages, hSrcFont, phDestFont);
2056 return map_font(hDC, dwCodePages, hSrcFont, phDestFont);
2059 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
2060 IMLangFontLink* iface,
2061 HFONT hFont)
2063 TRACE("(%p)->%p\n",iface, hFont);
2065 return release_font(hFont);
2068 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
2069 IMLangFontLink* iface)
2071 TRACE("(%p)\n",iface);
2073 return clear_font_cache();
2077 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
2079 fnIMLangFontLink_QueryInterface,
2080 fnIMLangFontLink_AddRef,
2081 fnIMLangFontLink_Release,
2082 fnIMLangFontLink_GetCharCodePages,
2083 fnIMLangFontLink_GetStrCodePages,
2084 fnIMLangFontLink_CodePageToCodePages,
2085 fnIMLangFontLink_CodePagesToCodePage,
2086 fnIMLangFontLink_GetFontCodePages,
2087 fnIMLangFontLink_MapFont,
2088 fnIMLangFontLink_ReleaseFont,
2089 fnIMLangFontLink_ResetFontMapping,
2092 /******************************************************************************/
2094 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
2096 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
2099 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
2100 IMultiLanguage* iface,
2101 REFIID riid,
2102 void** obj)
2104 MLang_impl *This = impl_from_IMultiLanguage( iface );
2105 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
2108 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
2110 MLang_impl *This = impl_from_IMultiLanguage( iface );
2111 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
2114 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
2116 MLang_impl *This = impl_from_IMultiLanguage( iface );
2117 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
2120 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
2121 IMultiLanguage* iface,
2122 UINT* cp)
2124 MLang_impl *This = impl_from_IMultiLanguage( iface );
2125 TRACE("(%p, %p)\n", This, cp);
2126 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
2129 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
2130 IMultiLanguage* iface,
2131 UINT uiCodePage,
2132 PMIMECPINFO pCodePageInfo)
2134 UINT i, n;
2135 MLang_impl *This = impl_from_IMultiLanguage( iface );
2137 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
2139 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2141 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2143 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2145 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2146 return S_OK;
2151 return S_FALSE;
2154 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
2155 IMultiLanguage* iface,
2156 UINT cp,
2157 UINT* family_cp)
2159 MLang_impl *This = impl_from_IMultiLanguage( iface );
2160 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2163 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2164 IMultiLanguage* iface,
2165 DWORD grfFlags,
2166 IEnumCodePage** ppEnumCodePage)
2168 MLang_impl *This = impl_from_IMultiLanguage( iface );
2170 TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
2172 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2175 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2176 IMultiLanguage* iface,
2177 BSTR Charset,
2178 PMIMECSETINFO pCharsetInfo)
2180 MLang_impl *This = impl_from_IMultiLanguage( iface );
2181 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2184 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2185 IMultiLanguage* iface,
2186 DWORD src_enc,
2187 DWORD dst_enc)
2189 MLang_impl *This = impl_from_IMultiLanguage( iface );
2190 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2193 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2194 IMultiLanguage* iface,
2195 DWORD* mode,
2196 DWORD src_enc,
2197 DWORD dst_enc,
2198 BYTE* src,
2199 UINT* src_size,
2200 BYTE* dest,
2201 UINT* dest_size)
2203 MLang_impl *This = impl_from_IMultiLanguage( iface );
2204 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2205 dst_enc, src, src_size, dest, dest_size);
2208 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2209 IMultiLanguage* iface,
2210 DWORD* mode,
2211 DWORD src_enc,
2212 CHAR* src,
2213 UINT* src_size,
2214 WCHAR* dest,
2215 UINT* dest_size)
2217 MLang_impl *This = impl_from_IMultiLanguage( iface );
2218 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2219 mode, src_enc, src, src_size, dest, dest_size);
2222 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2223 IMultiLanguage* iface,
2224 DWORD* mode,
2225 DWORD encoding,
2226 WCHAR* src,
2227 UINT* src_size,
2228 CHAR* dest,
2229 UINT* dest_size)
2231 MLang_impl *This = impl_from_IMultiLanguage(iface);
2232 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2233 mode, encoding, src, src_size, dest, dest_size);
2236 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2237 IMultiLanguage* iface)
2239 MLang_impl *This = impl_from_IMultiLanguage( iface );
2240 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2243 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2244 IMultiLanguage* iface,
2245 LCID lcid,
2246 BSTR* pbstrRfc1766)
2248 MLang_impl *This = impl_from_IMultiLanguage(iface);
2249 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2252 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2253 IMultiLanguage* iface,
2254 LCID* locale,
2255 BSTR rfc1766)
2257 MLang_impl *This = impl_from_IMultiLanguage(iface);
2258 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2261 /******************************************************************************/
2263 typedef struct tagEnumRfc1766_impl
2265 IEnumRfc1766 IEnumRfc1766_iface;
2266 LONG ref;
2267 RFC1766INFO *info;
2268 DWORD total, pos;
2269 } EnumRfc1766_impl;
2271 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2273 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2276 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2277 IEnumRfc1766 *iface,
2278 REFIID riid,
2279 void** ppvObject)
2281 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2283 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2285 if (IsEqualGUID(riid, &IID_IUnknown)
2286 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2288 IEnumRfc1766_AddRef(iface);
2289 TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
2290 *ppvObject = &This->IEnumRfc1766_iface;
2291 return S_OK;
2294 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2295 return E_NOINTERFACE;
2298 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2299 IEnumRfc1766 *iface)
2301 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2302 return InterlockedIncrement(&This->ref);
2305 static ULONG WINAPI fnIEnumRfc1766_Release(
2306 IEnumRfc1766 *iface)
2308 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2309 ULONG ref = InterlockedDecrement(&This->ref);
2311 TRACE("%p ref = %d\n", This, ref);
2312 if (ref == 0)
2314 TRACE("Destroying %p\n", This);
2315 HeapFree(GetProcessHeap(), 0, This->info);
2316 HeapFree(GetProcessHeap(), 0, This);
2318 return ref;
2321 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2322 IEnumRfc1766 *iface,
2323 IEnumRfc1766 **ppEnum)
2325 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2327 FIXME("%p %p\n", This, ppEnum);
2328 return E_NOTIMPL;
2331 static HRESULT WINAPI fnIEnumRfc1766_Next(
2332 IEnumRfc1766 *iface,
2333 ULONG celt,
2334 PRFC1766INFO rgelt,
2335 ULONG *pceltFetched)
2337 ULONG i;
2338 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2340 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
2342 if (!pceltFetched) return S_FALSE;
2343 *pceltFetched = 0;
2345 if (!rgelt) return S_FALSE;
2347 if (This->pos + celt > This->total)
2348 celt = This->total - This->pos;
2350 if (!celt) return S_FALSE;
2352 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2353 *pceltFetched = celt;
2354 This->pos += celt;
2356 for (i = 0; i < celt; i++)
2358 TRACE("#%u: %08x %s %s\n",
2359 i, rgelt[i].lcid,
2360 wine_dbgstr_w(rgelt[i].wszRfc1766),
2361 wine_dbgstr_w(rgelt[i].wszLocaleName));
2363 return S_OK;
2366 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2367 IEnumRfc1766 *iface)
2369 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2371 TRACE("%p\n", This);
2373 This->pos = 0;
2374 return S_OK;
2377 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2378 IEnumRfc1766 *iface,
2379 ULONG celt)
2381 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2383 TRACE("%p %u\n", This, celt);
2385 if (celt >= This->total) return S_FALSE;
2387 This->pos += celt;
2388 return S_OK;
2391 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2393 fnIEnumRfc1766_QueryInterface,
2394 fnIEnumRfc1766_AddRef,
2395 fnIEnumRfc1766_Release,
2396 fnIEnumRfc1766_Clone,
2397 fnIEnumRfc1766_Next,
2398 fnIEnumRfc1766_Reset,
2399 fnIEnumRfc1766_Skip
2402 struct enum_locales_data
2404 RFC1766INFO *info;
2405 DWORD total, allocated;
2408 static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
2410 WCHAR *end;
2411 struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
2412 RFC1766INFO *info;
2414 TRACE("%s\n", debugstr_w(locale));
2416 if (data->total >= data->allocated)
2418 data->allocated += 32;
2419 data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2420 if (!data->info) return FALSE;
2423 info = &data->info[data->total];
2425 info->lcid = wcstol(locale, &end, 16);
2426 if (*end) /* invalid number */
2427 return FALSE;
2429 info->wszRfc1766[0] = 0;
2430 lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
2432 info->wszLocaleName[0] = 0;
2433 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2434 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2436 data->total++;
2438 return TRUE;
2441 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2443 EnumRfc1766_impl *rfc;
2444 struct enum_locales_data data;
2446 TRACE("%04x, %p\n", LangId, ppEnum);
2448 rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2449 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2450 rfc->ref = 1;
2451 rfc->pos = 0;
2452 rfc->total = 0;
2454 data.total = 0;
2455 data.allocated = 160;
2456 data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2457 if (!data.info)
2459 HeapFree(GetProcessHeap(), 0, rfc);
2460 return E_OUTOFMEMORY;
2463 TlsSetValue(MLANG_tls_index, &data);
2464 EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
2465 TlsSetValue(MLANG_tls_index, NULL);
2467 TRACE("enumerated %d rfc1766 structures\n", data.total);
2469 if (!data.total)
2471 HeapFree(GetProcessHeap(), 0, data.info);
2472 HeapFree(GetProcessHeap(), 0, rfc);
2473 return E_FAIL;
2476 rfc->info = data.info;
2477 rfc->total = data.total;
2479 *ppEnum = &rfc->IEnumRfc1766_iface;
2480 return S_OK;
2483 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2484 IMultiLanguage *iface,
2485 IEnumRfc1766 **ppEnumRfc1766)
2487 MLang_impl *This = impl_from_IMultiLanguage( iface );
2489 TRACE("%p %p\n", This, ppEnumRfc1766);
2491 return EnumRfc1766_create(0, ppEnumRfc1766);
2494 /******************************************************************************/
2496 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2497 IMultiLanguage* iface,
2498 LCID Locale,
2499 PRFC1766INFO pRfc1766Info)
2501 LCTYPE type = LOCALE_SLANGUAGE;
2503 TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
2505 if (!pRfc1766Info)
2506 return E_INVALIDARG;
2508 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2509 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2510 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2512 if (!SUBLANGID(Locale))
2513 type = LOCALE_SENGLANGUAGE; /* suppress country */
2515 else
2517 if (!SUBLANGID(Locale)) {
2518 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2519 return E_FAIL;
2523 pRfc1766Info->lcid = Locale;
2524 pRfc1766Info->wszRfc1766[0] = 0;
2525 pRfc1766Info->wszLocaleName[0] = 0;
2527 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2528 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2529 return S_OK;
2531 /* Locale not supported */
2532 return E_INVALIDARG;
2535 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2536 IMultiLanguage* iface,
2537 UINT src_cp,
2538 UINT dst_cp,
2539 DWORD prop,
2540 IMLangConvertCharset** convert_charset)
2542 MLang_impl *This = impl_from_IMultiLanguage(iface);
2543 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2546 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2548 fnIMultiLanguage_QueryInterface,
2549 fnIMultiLanguage_AddRef,
2550 fnIMultiLanguage_Release,
2551 fnIMultiLanguage_GetNumberOfCodePageInfo,
2552 fnIMultiLanguage_GetCodePageInfo,
2553 fnIMultiLanguage_GetFamilyCodePage,
2554 fnIMultiLanguage_EnumCodePages,
2555 fnIMultiLanguage_GetCharsetInfo,
2556 fnIMultiLanguage_IsConvertible,
2557 fnIMultiLanguage_ConvertString,
2558 fnIMultiLanguage_ConvertStringToUnicode,
2559 fnIMultiLanguage_ConvertStringFromUnicode,
2560 fnIMultiLanguage_ConvertStringReset,
2561 fnIMultiLanguage_GetRfc1766FromLcid,
2562 fnIMultiLanguage_GetLcidFromRfc1766,
2563 fnIMultiLanguage_EnumRfc1766,
2564 fnIMultiLanguage_GetRfc1766Info,
2565 fnIMultiLanguage_CreateConvertCharset,
2569 /******************************************************************************/
2571 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2573 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2576 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2577 IMultiLanguage3* iface,
2578 REFIID riid,
2579 void** obj)
2581 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2583 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2585 if (IsEqualGUID(riid, &IID_IUnknown) ||
2586 IsEqualGUID(riid, &IID_IMultiLanguage))
2588 *obj = &This->IMultiLanguage_iface;
2590 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2591 IsEqualGUID(riid, &IID_IMLangFontLink))
2593 *obj = &This->IMLangFontLink_iface;
2595 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2597 *obj = &This->IMLangFontLink2_iface;
2599 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2600 IsEqualGUID(riid, &IID_IMultiLanguage3))
2602 *obj = &This->IMultiLanguage3_iface;
2604 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2606 *obj = &This->IMLangLineBreakConsole_iface;
2608 else
2610 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2611 *obj = NULL;
2612 return E_NOINTERFACE;
2615 IMultiLanguage3_AddRef(iface);
2616 return S_OK;
2619 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2621 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2622 return InterlockedIncrement(&This->ref);
2625 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2627 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2628 ULONG ref = InterlockedDecrement(&This->ref);
2630 TRACE("(%p)->(%d)\n", This, ref);
2631 if (ref == 0)
2633 HeapFree(GetProcessHeap(), 0, This);
2634 UnlockModule();
2637 return ref;
2640 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2641 IMultiLanguage3* iface,
2642 UINT* pcCodePage)
2644 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2646 TRACE("%p, %p\n", This, pcCodePage);
2648 if (!pcCodePage) return E_INVALIDARG;
2650 *pcCodePage = This->total_cp;
2651 return S_OK;
2654 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2656 CHARSETINFO csi;
2658 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2659 TCI_SRCCODEPAGE))
2660 mime_cp_info->bGDICharset = csi.ciCharset;
2661 else
2662 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2664 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2665 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2666 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2667 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
2668 mime_cp_info->wszDescription, ARRAY_SIZE(mime_cp_info->wszDescription));
2669 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
2670 mime_cp_info->wszWebCharset, ARRAY_SIZE(mime_cp_info->wszWebCharset));
2671 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
2672 mime_cp_info->wszHeaderCharset, ARRAY_SIZE(mime_cp_info->wszHeaderCharset));
2673 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
2674 mime_cp_info->wszBodyCharset, ARRAY_SIZE(mime_cp_info->wszBodyCharset));
2676 MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
2677 mime_cp_info->wszFixedWidthFont, ARRAY_SIZE(mime_cp_info->wszFixedWidthFont));
2678 MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
2679 mime_cp_info->wszProportionalFont, ARRAY_SIZE(mime_cp_info->wszProportionalFont));
2681 TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
2682 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2683 mime_cp_info->uiFamilyCodePage,
2684 wine_dbgstr_w(mime_cp_info->wszDescription),
2685 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2686 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2687 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2688 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2689 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2690 mime_cp_info->bGDICharset);
2693 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2694 IMultiLanguage3* iface,
2695 UINT uiCodePage,
2696 LANGID LangId,
2697 PMIMECPINFO pCodePageInfo)
2699 UINT i, n;
2700 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2702 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2704 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2706 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2708 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2710 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2711 return S_OK;
2716 return S_FALSE;
2719 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2720 IMultiLanguage3* iface,
2721 UINT uiCodePage,
2722 UINT* puiFamilyCodePage)
2724 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2727 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2728 IMultiLanguage3* iface,
2729 DWORD grfFlags,
2730 LANGID LangId,
2731 IEnumCodePage** ppEnumCodePage)
2733 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2735 TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2737 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2740 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2741 IMultiLanguage3* iface,
2742 BSTR Charset,
2743 PMIMECSETINFO pCharsetInfo)
2745 UINT i, n;
2746 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2748 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2750 if (!pCharsetInfo) return E_FAIL;
2752 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2754 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2756 WCHAR csetW[MAX_MIMECSET_NAME];
2758 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
2759 if (!lstrcmpiW(Charset, csetW))
2761 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2762 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2763 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2764 return S_OK;
2766 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2768 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2769 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2770 lstrcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2771 return S_OK;
2776 /* FIXME:
2777 * Since we do not support charsets like iso-2022-jp and do not have
2778 * them in our database as a primary (web_charset) encoding this loop
2779 * does an attempt to 'approximate' charset name by header_charset.
2781 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
2783 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2785 WCHAR csetW[MAX_MIMECSET_NAME];
2787 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
2788 if (!lstrcmpiW(Charset, csetW))
2790 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2791 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2792 lstrcpyW(pCharsetInfo->wszCharset, csetW);
2793 return S_OK;
2798 return E_FAIL;
2801 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2802 IMultiLanguage3* iface,
2803 DWORD dwSrcEncoding,
2804 DWORD dwDstEncoding)
2806 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2809 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2810 IMultiLanguage3* iface,
2811 DWORD* pdwMode,
2812 DWORD dwSrcEncoding,
2813 DWORD dwDstEncoding,
2814 BYTE* pSrcStr,
2815 UINT* pcSrcSize,
2816 BYTE* pDstStr,
2817 UINT* pcDstSize)
2819 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2820 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2823 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2824 IMultiLanguage3* iface,
2825 DWORD* pdwMode,
2826 DWORD dwEncoding,
2827 CHAR* pSrcStr,
2828 UINT* pcSrcSize,
2829 WCHAR* pDstStr,
2830 UINT* pcDstSize)
2832 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2833 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2836 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2837 IMultiLanguage3* iface,
2838 DWORD* pdwMode,
2839 DWORD dwEncoding,
2840 WCHAR* pSrcStr,
2841 UINT* pcSrcSize,
2842 CHAR* pDstStr,
2843 UINT* pcDstSize)
2845 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2846 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2849 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2850 IMultiLanguage3* iface)
2852 FIXME("\n");
2853 return E_NOTIMPL;
2856 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2857 IMultiLanguage3* iface,
2858 LCID lcid,
2859 BSTR* pbstrRfc1766)
2861 WCHAR buf[MAX_RFC1766_NAME];
2863 TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
2864 if (!pbstrRfc1766)
2865 return E_INVALIDARG;
2867 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2869 *pbstrRfc1766 = SysAllocString( buf );
2870 return S_OK;
2872 return E_FAIL;
2875 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2876 IMultiLanguage3* iface,
2877 LCID* pLocale,
2878 BSTR bstrRfc1766)
2880 HRESULT hr;
2881 IEnumRfc1766 *rfc1766;
2883 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2885 if (!pLocale || !bstrRfc1766)
2886 return E_INVALIDARG;
2888 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2889 if (FAILED(hr))
2890 return hr;
2892 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2894 IEnumRfc1766_Release(rfc1766);
2895 return hr;
2898 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2899 IMultiLanguage3* iface,
2900 LANGID LangId,
2901 IEnumRfc1766** ppEnumRfc1766)
2903 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2905 TRACE("%p %p\n", This, ppEnumRfc1766);
2907 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2910 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2911 IMultiLanguage3* iface,
2912 LCID Locale,
2913 LANGID LangId,
2914 PRFC1766INFO pRfc1766Info)
2916 static LANGID last_lang = -1;
2917 LCTYPE type = LOCALE_SLANGUAGE;
2919 TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2921 if (!pRfc1766Info)
2922 return E_INVALIDARG;
2924 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2925 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2926 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2928 if (!SUBLANGID(Locale))
2929 type = LOCALE_SENGLANGUAGE; /* suppress country */
2931 else
2933 if (!SUBLANGID(Locale)) {
2934 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2935 return E_FAIL;
2939 pRfc1766Info->lcid = Locale;
2940 pRfc1766Info->wszRfc1766[0] = 0;
2941 pRfc1766Info->wszLocaleName[0] = 0;
2943 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2944 (last_lang != LangId)) {
2945 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2946 last_lang = LangId;
2949 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2950 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2951 return S_OK;
2953 /* Locale not supported */
2954 return E_INVALIDARG;
2957 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2958 IMultiLanguage3* iface,
2959 UINT src_cp,
2960 UINT dst_cp,
2961 DWORD prop,
2962 IMLangConvertCharset** convert_charset)
2964 HRESULT hr;
2966 TRACE("(%u %u 0x%08x %p)\n", src_cp, dst_cp, prop, convert_charset);
2968 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2969 if (FAILED(hr)) return hr;
2971 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2974 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2975 IMultiLanguage3* iface,
2976 DWORD* pdwMode,
2977 DWORD dwFlag,
2978 WCHAR* lpFallBack,
2979 DWORD dwSrcEncoding,
2980 DWORD dwDstEncoding,
2981 IStream* pstmIn,
2982 IStream* pstmOut)
2984 char *src, *dst = NULL;
2985 INT srclen, dstlen;
2986 STATSTG stat;
2987 HRESULT hr;
2989 TRACE("%p %0x8 %s %u %u %p %p\n",
2990 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2992 FIXME("dwFlag and lpFallBack not handled\n");
2994 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2995 if (FAILED(hr)) return hr;
2997 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
2998 if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
3000 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
3001 if (FAILED(hr)) goto exit;
3003 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
3004 if (FAILED(hr)) goto exit;
3006 if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
3008 hr = E_OUTOFMEMORY;
3009 goto exit;
3011 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
3012 if (FAILED(hr)) goto exit;
3014 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
3016 exit:
3017 HeapFree(GetProcessHeap(), 0, src);
3018 HeapFree(GetProcessHeap(), 0, dst);
3019 return hr;
3022 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
3023 IMultiLanguage3* iface,
3024 DWORD* pdwMode,
3025 DWORD dwEncoding,
3026 CHAR* pSrcStr,
3027 UINT* pcSrcSize,
3028 WCHAR* pDstStr,
3029 UINT* pcDstSize,
3030 DWORD dwFlag,
3031 WCHAR* lpFallBack)
3033 if (dwFlag || lpFallBack)
3034 FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
3035 dwFlag, dwFlag, lpFallBack);
3037 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
3038 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3041 /*****************************************************************************
3042 * MultiLanguage2::ConvertStringToUnicodeEx
3044 * Translates the multibyte string from the specified code page to Unicode.
3046 * PARAMS
3047 * see ConvertStringToUnicode
3048 * dwFlag
3049 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
3050 * instead unconvertible characters.
3052 * RETURNS
3053 * S_OK Success.
3054 * S_FALSE The conversion is not supported.
3055 * E_FAIL Some error has occurred.
3057 * TODO: handle dwFlag and lpFallBack
3059 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
3060 IMultiLanguage3* This,
3061 DWORD* pdwMode,
3062 DWORD dwEncoding,
3063 WCHAR* pSrcStr,
3064 UINT* pcSrcSize,
3065 CHAR* pDstStr,
3066 UINT* pcDstSize,
3067 DWORD dwFlag,
3068 WCHAR* lpFallBack)
3070 FIXME("\n");
3071 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
3072 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
3075 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
3076 IMultiLanguage3* iface,
3077 DWORD dwFlag,
3078 DWORD dwPrefWinCodePage,
3079 IStream* pstmIn,
3080 DetectEncodingInfo* lpEncoding,
3081 INT* pnScores)
3083 FIXME("\n");
3084 return E_NOTIMPL;
3087 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
3088 IMultiLanguage3* iface,
3089 DWORD dwFlag,
3090 DWORD dwPrefWinCodePage,
3091 CHAR* pSrcStr,
3092 INT* pcSrcSize,
3093 DetectEncodingInfo* lpEncoding,
3094 INT* pnScores)
3096 FIXME("\n");
3097 return E_NOTIMPL;
3100 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
3101 IMultiLanguage3* iface,
3102 UINT uiCodePage,
3103 HWND hwnd)
3105 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
3108 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
3109 IMultiLanguage3* iface,
3110 UINT uiCodePage,
3111 LCID lcid,
3112 LPWSTR lpWideCharStr,
3113 int cchWideChar)
3115 /* Find first instance */
3116 unsigned int i,n;
3118 TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
3119 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3121 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3123 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3125 MultiByteToWideChar(CP_ACP, 0,
3126 mlang_data[i].mime_cp_info[n].description,
3127 -1, lpWideCharStr, cchWideChar);
3128 return S_OK;
3133 return S_FALSE;
3136 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
3137 IMultiLanguage3* iface,
3138 UINT uiCodePage)
3140 TRACE("%u\n", uiCodePage);
3142 /* FIXME: the installable set is usually larger than the set of valid codepages */
3143 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
3146 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
3147 IMultiLanguage3* iface,
3148 MIMECONTF dwSource)
3150 FIXME("0x%08x\n", dwSource);
3151 return S_OK;
3154 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
3155 IMultiLanguage3* iface,
3156 UINT* pnScripts)
3158 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3160 TRACE("%p %p\n", This, pnScripts);
3162 if (!pnScripts) return S_FALSE;
3164 *pnScripts = This->total_scripts;
3165 return S_OK;
3168 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3169 IMultiLanguage3* iface,
3170 DWORD dwFlags,
3171 LANGID LangId,
3172 IEnumScript** ppEnumScript)
3174 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3176 TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3178 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3181 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3182 IMultiLanguage3* iface,
3183 UINT uiCodePage,
3184 HWND hwnd,
3185 DWORD dwfIODControl)
3187 unsigned int i;
3188 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3190 TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
3192 /* quick check for kernel32 supported code pages */
3193 if (IsValidCodePage(uiCodePage))
3194 return S_OK;
3196 /* check for mlang supported code pages */
3197 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3199 UINT n;
3200 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3202 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3203 return S_OK;
3207 if (dwfIODControl != CPIOD_PEEK)
3208 FIXME("Request to install codepage language pack not handled\n");
3210 return S_FALSE;
3213 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3214 IMultiLanguage3 *iface,
3215 DWORD dwFlags,
3216 LPCWSTR lpWideCharStr,
3217 UINT cchWideChar,
3218 UINT *puiPreferredCodePages,
3219 UINT nPreferredCodePages,
3220 UINT *puiDetectedCodePages,
3221 UINT *pnDetectedCodePages,
3222 WCHAR *lpSpecialChar)
3224 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3226 FIXME("(%p)->(%08x %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3227 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3228 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3229 debugstr_w(lpSpecialChar));
3231 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3232 return E_INVALIDARG;
3234 puiDetectedCodePages[0] = CP_UTF8;
3235 *pnDetectedCodePages = 1;
3236 return S_OK;
3239 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3240 IMultiLanguage3 *iface,
3241 DWORD dwFlags,
3242 IStream *pStrIn,
3243 UINT *puiPreferredCodePages,
3244 UINT nPreferredCodePages,
3245 UINT *puiDetectedCodePages,
3246 UINT *pnDetectedCodePages,
3247 WCHAR *lpSpecialChar)
3249 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3251 FIXME("(%p)->(%08x %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3252 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3253 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3254 debugstr_w(lpSpecialChar));
3256 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3257 return E_INVALIDARG;
3259 puiDetectedCodePages[0] = CP_UTF8;
3260 *pnDetectedCodePages = 1;
3261 return S_OK;
3264 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3266 fnIMultiLanguage3_QueryInterface,
3267 fnIMultiLanguage3_AddRef,
3268 fnIMultiLanguage3_Release,
3269 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3270 fnIMultiLanguage3_GetCodePageInfo,
3271 fnIMultiLanguage3_GetFamilyCodePage,
3272 fnIMultiLanguage3_EnumCodePages,
3273 fnIMultiLanguage3_GetCharsetInfo,
3274 fnIMultiLanguage3_IsConvertible,
3275 fnIMultiLanguage3_ConvertString,
3276 fnIMultiLanguage3_ConvertStringToUnicode,
3277 fnIMultiLanguage3_ConvertStringFromUnicode,
3278 fnIMultiLanguage3_ConvertStringReset,
3279 fnIMultiLanguage3_GetRfc1766FromLcid,
3280 fnIMultiLanguage3_GetLcidFromRfc1766,
3281 fnIMultiLanguage3_EnumRfc1766,
3282 fnIMultiLanguage3_GetRfc1766Info,
3283 fnIMultiLanguage3_CreateConvertCharset,
3284 fnIMultiLanguage3_ConvertStringInIStream,
3285 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3286 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3287 fnIMultiLanguage3_DetectCodepageInIStream,
3288 fnIMultiLanguage3_DetectInputCodepage,
3289 fnIMultiLanguage3_ValidateCodePage,
3290 fnIMultiLanguage3_GetCodePageDescription,
3291 fnIMultiLanguage3_IsCodePageInstallable,
3292 fnIMultiLanguage3_SetMimeDBSource,
3293 fnIMultiLanguage3_GetNumberOfScripts,
3294 fnIMultiLanguage3_EnumScripts,
3295 fnIMultiLanguage3_ValidateCodePageEx,
3296 fnIMultiLanguage3_DetectOutboundCodePage,
3297 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3300 /******************************************************************************/
3302 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3304 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3307 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3308 IMLangFontLink2 * iface,
3309 REFIID riid,
3310 void** ppvObject)
3312 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3313 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3316 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3318 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3319 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3322 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3324 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3325 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3328 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3329 WCHAR ch_src, DWORD *ret_codepages)
3331 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3332 unsigned int i;
3334 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3336 *ret_codepages = 0;
3338 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3340 BOOL used_dc;
3341 CHAR buf;
3343 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3344 &ch_src, 1, &buf, 1, NULL, &used_dc);
3346 /* If default char is not used, current codepage include the given symbol */
3347 if (!used_dc)
3349 DWORD codepages;
3351 IMLangFontLink2_CodePageToCodePages(iface,
3352 mlang_data[i].family_codepage, &codepages);
3353 *ret_codepages |= codepages;
3356 return S_OK;
3359 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3360 const WCHAR *src, LONG src_len, DWORD priority_cp,
3361 DWORD *codepages, LONG *ret_len)
3363 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3364 LONG i;
3365 DWORD cps = 0;
3367 TRACE("(%p)->(%s:%d %x %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3368 codepages, ret_len);
3370 if (codepages) *codepages = 0;
3371 if (ret_len) *ret_len = 0;
3373 if (!src || !src_len || src_len < 0)
3374 return E_INVALIDARG;
3376 for (i = 0; i < src_len; i++)
3378 DWORD cp;
3379 HRESULT ret;
3381 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3382 if (ret != S_OK) return E_FAIL;
3384 if (!cps) cps = cp;
3385 else cps &= cp;
3387 /* FIXME: not tested */
3388 if (priority_cp & cps) break;
3391 if (codepages) *codepages = cps;
3392 if (ret_len) *ret_len = min( i + 1, src_len );
3393 return S_OK;
3396 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3397 UINT codepage,
3398 DWORD *codepages)
3400 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3401 CHARSETINFO cs;
3402 BOOL rc;
3404 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3406 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3407 if (rc)
3409 *codepages = cs.fs.fsCsb[0];
3410 TRACE("resulting codepages 0x%x\n", *codepages);
3411 return S_OK;
3414 TRACE("codepage not found\n");
3415 *codepages = 0;
3416 return E_FAIL;
3419 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3420 DWORD codepages, UINT def_codepage, UINT *codepage)
3422 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3423 DWORD mask = 0;
3424 CHARSETINFO cs;
3425 BOOL rc;
3426 UINT i;
3428 TRACE("(%p)->(0x%x %u %p)\n", This, codepages, def_codepage, codepage);
3430 *codepage = 0;
3432 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3433 if (rc && (codepages & cs.fs.fsCsb[0]))
3435 TRACE("Found Default Codepage\n");
3436 *codepage = def_codepage;
3437 return S_OK;
3440 for (i = 0; i < 32; i++)
3442 mask = 1 << i;
3443 if (codepages & mask)
3445 DWORD Csb[2];
3446 Csb[0] = mask;
3447 Csb[1] = 0x0;
3448 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3449 if (!rc)
3450 continue;
3452 TRACE("Falling back to least significant found CodePage %u\n",
3453 cs.ciACP);
3454 *codepage = cs.ciACP;
3455 return S_OK;
3459 TRACE("no codepage found\n");
3460 return E_FAIL;
3463 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3464 HDC hdc, HFONT hfont, DWORD *codepages)
3466 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3467 FONTSIGNATURE fontsig;
3468 HFONT old_font;
3470 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3472 old_font = SelectObject(hdc, hfont);
3473 GetTextCharsetInfo(hdc, &fontsig, 0);
3474 SelectObject(hdc, old_font);
3476 *codepages = fontsig.fsCsb[0];
3477 TRACE("ret 0x%x\n", fontsig.fsCsb[0]);
3479 return S_OK;
3482 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3483 HFONT hFont)
3485 TRACE("(%p)->%p\n",This, hFont);
3487 return release_font(hFont);
3490 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3492 TRACE("(%p)\n",This);
3494 return clear_font_cache();
3497 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3498 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3500 HFONT old_font;
3502 TRACE("(%p)->%p %08x %04x %p\n",This, hDC, dwCodePages, chSrc, pFont);
3504 if (!hDC) return E_FAIL;
3506 if (dwCodePages != 0)
3508 old_font = GetCurrentObject(hDC, OBJ_FONT);
3509 return map_font(hDC, dwCodePages, old_font, pFont);
3511 else
3513 if (pFont == NULL) return E_INVALIDARG;
3514 FIXME("the situation where dwCodepages is set to zero is not implemented\n");
3515 return E_FAIL;
3519 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3520 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3522 DWORD size;
3523 GLYPHSET *gs;
3525 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3527 if (!puiRanges) return E_INVALIDARG;
3528 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3529 if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3531 GetFontUnicodeRanges(hDC, gs);
3532 *puiRanges = gs->cRanges;
3533 if (pUranges)
3535 UINT i;
3536 for (i = 0; i < gs->cRanges; i++)
3538 if (i >= *puiRanges) break;
3539 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3540 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3542 *puiRanges = i;
3544 HeapFree(GetProcessHeap(), 0, gs);
3545 return S_OK;
3548 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3549 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3550 SCRIPTFONTINFO *pScriptFont)
3552 UINT i, j;
3554 TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3556 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3558 for (i = 0, j = 0; i < ARRAY_SIZE(mlang_data); i++)
3560 if (sid == mlang_data[i].sid)
3562 if (pScriptFont)
3564 if (j >= *puiFonts) break;
3566 pScriptFont[j].scripts = (SCRIPT_IDS)1 << mlang_data[i].sid;
3567 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3569 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
3570 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3572 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3574 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
3575 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3578 j++;
3581 *puiFonts = j;
3582 return S_OK;
3585 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3586 UINT uiCodePage, SCRIPT_ID *pSid)
3588 UINT i;
3590 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3592 if (uiCodePage == CP_UNICODE) return E_FAIL;
3594 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3596 if (uiCodePage == mlang_data[i].family_codepage)
3598 if (pSid) *pSid = mlang_data[i].sid;
3599 return S_OK;
3602 return E_FAIL;
3605 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3607 fnIMLangFontLink2_QueryInterface,
3608 fnIMLangFontLink2_AddRef,
3609 fnIMLangFontLink2_Release,
3610 fnIMLangFontLink2_GetCharCodePages,
3611 fnIMLangFontLink2_GetStrCodePages,
3612 fnIMLangFontLink2_CodePageToCodePages,
3613 fnIMLangFontLink2_CodePagesToCodePage,
3614 fnIMLangFontLink2_GetFontCodePages,
3615 fnIMLangFontLink2_ReleaseFont,
3616 fnIMLangFontLink2_ResetFontMapping,
3617 fnIMLangFontLink2_MapFont,
3618 fnIMLangFontLink2_GetFontUnicodeRanges,
3619 fnIMLangFontLink2_GetScriptFontInfo,
3620 fnIMLangFontLink2_CodePageToScriptID
3623 /******************************************************************************/
3625 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3627 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3630 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3631 IMLangLineBreakConsole* iface,
3632 REFIID riid,
3633 void** ppvObject)
3635 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3636 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3639 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3640 IMLangLineBreakConsole* iface )
3642 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3643 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3646 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3647 IMLangLineBreakConsole* iface )
3649 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3650 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3653 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3654 IMLangLineBreakConsole* iface,
3655 IMLangString* pSrcMLStr,
3656 LONG lSrcPos,
3657 LONG lSrcLen,
3658 LONG cMinColumns,
3659 LONG cMaxColumns,
3660 LONG* plLineLen,
3661 LONG* plSkipLen)
3663 FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3664 return E_NOTIMPL;
3667 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3668 IMLangLineBreakConsole* iface,
3669 LCID locale,
3670 const WCHAR* pszSrc,
3671 LONG cchSrc,
3672 LONG cMaxColumns,
3673 LONG* pcchLine,
3674 LONG* pcchSkip )
3676 FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3678 *pcchLine = cchSrc;
3679 *pcchSkip = 0;
3680 return S_OK;
3683 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3684 IMLangLineBreakConsole* iface,
3685 LCID locale,
3686 UINT uCodePage,
3687 const CHAR* pszSrc,
3688 LONG cchSrc,
3689 LONG cMaxColumns,
3690 LONG* pcchLine,
3691 LONG* pcchSkip)
3693 LONG i, line = cchSrc, skip = 0;
3695 FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3697 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3699 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3701 if (pszSrc[i] == ' ')
3703 while (i >= 0 && pszSrc[i] == ' ')
3705 i--;
3706 line--;
3707 skip++;
3709 break;
3713 *pcchLine = line;
3714 *pcchSkip = skip;
3715 return S_OK;
3718 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3720 fnIMLangLineBreakConsole_QueryInterface,
3721 fnIMLangLineBreakConsole_AddRef,
3722 fnIMLangLineBreakConsole_Release,
3723 fnIMLangLineBreakConsole_BreakLineML,
3724 fnIMLangLineBreakConsole_BreakLineW,
3725 fnIMLangLineBreakConsole_BreakLineA
3728 struct convert_charset {
3729 IMLangConvertCharset IMLangConvertCharset_iface;
3730 LONG ref;
3732 UINT src_cp;
3733 UINT dst_cp;
3736 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3738 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3741 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3743 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3745 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3747 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3749 *obj = &This->IMLangConvertCharset_iface;
3750 IMLangConvertCharset_AddRef(iface);
3751 return S_OK;
3754 *obj = NULL;
3755 return E_NOINTERFACE;
3758 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3760 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3761 ULONG ref = InterlockedIncrement(&This->ref);
3762 TRACE("(%p)->(%u)\n", This, ref);
3763 return ref;
3766 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3768 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3769 ULONG ref = InterlockedDecrement(&This->ref);
3771 TRACE("(%p)->(%u)\n", This, ref);
3772 if (!ref)
3774 HeapFree(GetProcessHeap(), 0, This);
3775 UnlockModule();
3778 return ref;
3781 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3782 UINT src_cp, UINT dst_cp, DWORD prop)
3784 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3786 TRACE("(%p)->(%u %u 0x%08x)\n", This, src_cp, dst_cp, prop);
3788 prop &= ~MLCONVCHARF_USEDEFCHAR;
3789 if (prop)
3790 FIXME("property 0x%08x not supported\n", prop);
3792 This->src_cp = src_cp;
3793 This->dst_cp = dst_cp;
3795 return S_OK;
3798 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3800 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3802 TRACE("(%p)->(%p)\n", This, src_cp);
3804 if (!src_cp) return E_INVALIDARG;
3805 *src_cp = This->src_cp;
3806 return S_OK;
3809 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3811 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3813 TRACE("(%p)->(%p)\n", This, dst_cp);
3815 if (!dst_cp) return E_INVALIDARG;
3816 *dst_cp = This->dst_cp;
3817 return S_OK;
3820 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3822 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3823 FIXME("(%p)->(%p): stub\n", This, prop);
3824 return E_NOTIMPL;
3827 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3828 UINT *src_size, BYTE *dest, UINT *dest_size)
3830 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3831 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3832 return E_NOTIMPL;
3835 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3836 UINT *src_size, WCHAR *dest, UINT *dest_size)
3838 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3839 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3840 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3843 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3844 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3846 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3847 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3848 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3851 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3853 MLangConvertCharset_QueryInterface,
3854 MLangConvertCharset_AddRef,
3855 MLangConvertCharset_Release,
3856 MLangConvertCharset_Initialize,
3857 MLangConvertCharset_GetSourceCodePage,
3858 MLangConvertCharset_GetDestinationCodePage,
3859 MLangConvertCharset_GetProperty,
3860 MLangConvertCharset_DoConversion,
3861 MLangConvertCharset_DoConversionToUnicode,
3862 MLangConvertCharset_DoConversionFromUnicode
3865 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3867 MLang_impl *mlang;
3868 UINT i;
3870 TRACE("Creating MultiLanguage object\n");
3872 if( pUnkOuter )
3873 return CLASS_E_NOAGGREGATION;
3875 mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3876 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3877 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3878 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3879 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3880 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3882 mlang->total_cp = 0;
3883 for (i = 0; i < ARRAY_SIZE(mlang_data); i++)
3884 mlang->total_cp += mlang_data[i].number_of_cp;
3886 /* do not enumerate unicode flavours */
3887 mlang->total_scripts = ARRAY_SIZE(mlang_data) - 1;
3889 mlang->ref = 1;
3890 *ppObj = &mlang->IMultiLanguage_iface;
3891 TRACE("returning %p\n", mlang);
3893 LockModule();
3895 return S_OK;
3898 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3900 struct convert_charset *convert;
3902 if (outer)
3903 return CLASS_E_NOAGGREGATION;
3905 *obj = NULL;
3907 convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3908 if (!convert) return E_OUTOFMEMORY;
3910 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3911 convert->ref = 1;
3913 *obj = &convert->IMLangConvertCharset_iface;
3915 LockModule();
3917 return S_OK;
3920 /******************************************************************************/
3922 HRESULT WINAPI DllCanUnloadNow(void)
3924 return dll_count == 0 ? S_OK : S_FALSE;
3927 static BOOL register_codepages(void)
3929 const struct mlang_data *family;
3930 const MIME_CP_INFO *info;
3931 HKEY db_key, key;
3932 WCHAR buf[32];
3933 LSTATUS status;
3935 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"MIME\\Database\\Codepage", &db_key);
3936 if (status != ERROR_SUCCESS)
3937 return FALSE;
3939 for (family = mlang_data; family < mlang_data + ARRAY_SIZE(mlang_data); family++)
3941 for (info = family->mime_cp_info; info < family->mime_cp_info + family->number_of_cp; info++)
3943 swprintf(buf, ARRAY_SIZE(buf), L"%u", info->cp);
3944 status = RegCreateKeyW(db_key, buf, &key);
3945 if (status != ERROR_SUCCESS)
3946 continue;
3948 RegSetValueExA(key, "BodyCharset", 0, REG_SZ, (BYTE*)info->body_charset,
3949 strlen(info->body_charset) + 1);
3951 if (info->cp == family->family_codepage)
3953 RegSetValueExA(key, "FixedWidthFont", 0, REG_SZ, (BYTE*)family->fixed_font,
3954 strlen(family->fixed_font) + 1);
3955 RegSetValueExA(key, "ProportionalFont", 0, REG_SZ, (BYTE*)family->proportional_font,
3956 strlen(family->proportional_font) + 1);
3958 else
3960 RegSetValueExW(key, L"Family", 0, REG_DWORD, (BYTE*)&family->family_codepage,
3961 sizeof(family->family_codepage));
3964 RegCloseKey(key);
3968 RegCloseKey(db_key);
3969 return TRUE;
3972 /***********************************************************************
3973 * DllRegisterServer (MLANG.@)
3975 HRESULT WINAPI DllRegisterServer(void)
3977 if(!register_codepages())
3978 return E_FAIL;
3979 return __wine_register_resources( instance );
3982 /***********************************************************************
3983 * DllUnregisterServer (MLANG.@)
3985 HRESULT WINAPI DllUnregisterServer(void)
3987 return __wine_unregister_resources( instance );
3990 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
3992 if (!unknown) return E_INVALIDARG;
3994 FIXME("%p: stub\n", unknown);
3996 return S_FALSE;