user32/tests: Separate WS_EX_TOPMOST tests from SetWindowPos ones.
[wine.git] / dlls / mlang / mlang.c
blob47f9d9882ff8618ec5b7691f13f130fc60f54fbf
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
24 #include "config.h"
26 #include <stdarg.h>
27 #include <stdio.h>
29 #define COBJMACROS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "ole2.h"
36 #include "objbase.h"
37 #include "rpcproxy.h"
38 #include "mlang.h"
39 #include "mimeole.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(mlang);
46 #include "initguid.h"
48 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
49 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj);
50 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum);
52 static HINSTANCE instance;
53 static DWORD MLANG_tls_index; /* to store various per thead data */
55 /* FIXME:
56 * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
57 * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
60 typedef struct
62 const char *description;
63 UINT cp;
64 DWORD flags;
65 const char *web_charset;
66 const char *header_charset;
67 const char *body_charset;
68 const WCHAR *alias;
69 } MIME_CP_INFO;
71 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
72 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
74 static const MIME_CP_INFO arabic_cp[] =
76 { "Arabic (864)",
77 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
78 MIMECONTF_MIME_LATEST,
79 "ibm864", "ibm864", "ibm864" },
80 { "Arabic (1006)",
81 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
82 MIMECONTF_MIME_LATEST,
83 "ibm1006", "ibm1006", "ibm1006" },
84 { "Arabic (Windows)",
85 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
86 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
87 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
88 "windows-1256", "windows-1256", "windows-1256" },
89 { "Arabic (ISO)",
90 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
91 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
92 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
93 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
94 "iso-8859-6", "iso-8859-6", "iso-8859-6" }
96 static const MIME_CP_INFO baltic_cp[] =
98 { "Baltic (DOS)",
99 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
100 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
101 "ibm775", "ibm775", "ibm775" },
102 { "Baltic (Windows)",
103 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
104 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
105 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
106 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
107 "windows-1257", "windows-1257", "windows-1257" },
108 { "Baltic (ISO)",
109 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
110 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
111 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
112 MIMECONTF_MIME_LATEST,
113 "iso-8859-4", "iso-8859-4", "iso-8859-4" },
114 { "Estonian (ISO)",
115 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
116 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
117 "iso-8859-13", "iso-8859-13", "iso-8859-13" }
119 static const MIME_CP_INFO chinese_simplified_cp[] =
121 { "Chinese Simplified (Auto-Select)",
122 50936, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
123 MIMECONTF_MIME_LATEST,
124 "_autodetect_chs", "_autodetect_chs", "_autodetect_chs" },
125 { "Chinese Simplified (GB2312)",
126 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
127 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
128 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
129 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
130 "gb2312", "gb2312", "gb2312" },
131 { "Chinese Simplified (GB2312-80)",
132 20936, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
133 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
134 "x-cp20936", "x-cp20936", "x-cp20936" },
135 { "Chinese Simplified (HZ)",
136 52936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
137 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
138 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
139 MIMECONTF_MIME_LATEST,
140 "hz-gb-2312", "hz-gb-2312", "hz-gb-2312" },
141 { "Chinese Simplified (GB18030)",
142 54936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
143 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
144 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
145 MIMECONTF_MIME_LATEST,
146 "GB18030", "GB18030", "GB18030" },
147 { "Chinese Simplified (GBK)",
148 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
149 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
150 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
151 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
152 "gbk", "gbk", "gbk" }
154 static const MIME_CP_INFO chinese_traditional_cp[] =
156 { "Chinese Traditional (Auto-Select)",
157 50950, MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
158 MIMECONTF_MIME_LATEST,
159 "_autodetect_cht", "_autodetect_cht", "_autodetect_cht" },
160 { "Chinese Traditional (Big5)",
161 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
162 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
163 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
164 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
165 "big5", "big5", "big5" },
166 { "Chinese Traditional (CNS)",
167 20000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
168 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
169 "x-Chinese-CNS", "x-Chinese-CNS", "x-Chinese-CNS" }
171 static const MIME_CP_INFO central_european_cp[] =
173 { "Central European (DOS)",
174 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
175 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
176 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
177 "ibm852", "ibm852", "ibm852" },
178 { "Central European (Windows)",
179 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
180 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
181 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
182 MIMECONTF_MIME_LATEST,
183 "windows-1250", "windows-1250", "windows-1250" },
184 { "Central European (Mac)",
185 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
186 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
187 "x-mac-ce", "x-mac-ce", "x-mac-ce" },
188 { "Central European (ISO)",
189 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
190 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
191 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
192 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
193 "iso-8859-2", "iso-8859-2", "iso-8859-2" }
195 static const MIME_CP_INFO cyrillic_cp[] =
197 { "OEM Cyrillic",
198 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
199 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
200 "ibm855", "ibm855", "ibm855" },
201 { "Cyrillic (DOS)",
202 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
203 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
204 MIMECONTF_MIME_LATEST,
205 "cp866", "cp866", "cp866" },
206 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
207 { "Cyrillic (KOI8-R)",
208 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
209 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
210 "koi8-r", "koi8-r", "koi8-r" },
211 #endif
212 { "Cyrillic (Windows)",
213 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
214 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
215 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
216 "windows-1251", "windows-1251", "windows-1251" },
217 { "Cyrillic (Mac)",
218 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
219 MIMECONTF_MIME_LATEST,
220 "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
221 { "Cyrillic (KOI8-R)",
222 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
223 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
224 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
225 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
226 "koi8-r", "koi8-r", "koi8-r" },
227 { "Cyrillic (KOI8-U)",
228 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
229 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
230 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
231 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
232 "koi8-u", "koi8-u", "koi8-u" },
233 { "Cyrillic (ISO)",
234 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
235 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
236 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
237 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
238 "iso-8859-5", "iso-8859-5", "iso-8859-5" }
240 static const MIME_CP_INFO greek_cp[] =
242 { "Greek (DOS)",
243 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
244 MIMECONTF_MIME_LATEST,
245 "ibm737", "ibm737", "ibm737" },
246 { "Greek, Modern (DOS)",
247 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
248 MIMECONTF_MIME_LATEST,
249 "ibm869", "ibm869", "ibm869" },
250 { "IBM EBCDIC (Greek Modern)",
251 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
252 MIMECONTF_MIME_LATEST,
253 "cp875", "cp875", "cp875" },
254 { "Greek (Windows)",
255 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
256 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
257 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
258 "windows-1253", "windows-1253", "windows-1253" },
259 { "Greek (Mac)",
260 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
261 MIMECONTF_MIME_LATEST,
262 "x-mac-greek", "x-mac-greek", "x-mac-greek" },
263 { "Greek (ISO)",
264 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
265 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
266 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
267 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
268 "iso-8859-7", "iso-8859-7", "iso-8859-7" }
270 static const MIME_CP_INFO hebrew_cp[] =
272 { "Hebrew (424)",
273 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
274 MIMECONTF_MIME_LATEST,
275 "ibm424", "ibm424", "ibm424" },
276 { "Hebrew (856)",
277 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
278 MIMECONTF_MIME_LATEST,
279 "cp856", "cp856", "cp856" },
280 { "Hebrew (DOS)",
281 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
282 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
283 MIMECONTF_MIME_LATEST,
284 "dos-862", "dos-862", "dos-862" },
285 { "Hebrew (Windows)",
286 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
287 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
288 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
289 "windows-1255", "windows-1255", "windows-1255" },
290 { "Hebrew (ISO-Visual)",
291 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
292 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
293 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
294 "iso-8859-8", "iso-8859-8", "iso-8859-8" }
296 static const MIME_CP_INFO japanese_cp[] =
298 { "Japanese (Auto-Select)",
299 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
300 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
301 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
302 "_autodetect", "_autodetect", "_autodetect" },
303 { "Japanese (EUC)",
304 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
305 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
306 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
307 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
308 "euc-jp", "euc-jp", "euc-jp" },
309 { "Japanese (JIS)",
310 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
311 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
312 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
313 MIMECONTF_MIME_IE4,
314 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
315 { "Japanese (JIS 0208-1990 and 0212-1990)",
316 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
317 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
318 "EUC-JP","EUC-JP","EUC-JP"},
319 { "Japanese (JIS-Allow 1 byte Kana)",
320 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
321 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
322 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
323 "csISO2022JP","iso-2022-jp","iso-2022-jp"},
324 { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
325 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
326 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
327 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
328 { "Japanese (Mac)",
329 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
330 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
331 "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
332 { "Japanese (Shift-JIS)",
333 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
334 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
335 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
336 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
337 "shift_jis", "iso-2022-jp", "iso-2022-jp" }
339 static const MIME_CP_INFO korean_cp[] =
341 { "Korean",
342 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
343 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
344 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
345 MIMECONTF_MIME_LATEST,
346 "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
348 static const MIME_CP_INFO thai_cp[] =
350 { "Thai (Windows)",
351 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
352 "ibm-thai", "ibm-thai", "ibm-thai" }
354 static const MIME_CP_INFO turkish_cp[] =
356 { "Turkish (DOS)",
357 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
358 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
359 "ibm857", "ibm857", "ibm857" },
360 { "IBM EBCDIC (Turkish Latin-5)",
361 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
362 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
363 "ibm1026", "ibm1026", "ibm1026" },
364 { "Turkish (Windows)",
365 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
366 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
367 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
368 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
369 "windows-1254", "windows-1254", "windows-1254" },
370 { "Turkish (Mac)",
371 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
372 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
373 "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
374 { "Latin 3 (ISO)",
375 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
376 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
377 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
378 "iso-8859-3", "iso-8859-3", "iso-8859-3" },
379 { "Turkish (ISO)",
380 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
381 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
382 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
383 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
384 "iso-8859-9", "iso-8859-9", "iso-8859-9" }
386 static const MIME_CP_INFO vietnamese_cp[] =
388 { "Vietnamese (Windows)",
389 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
390 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
391 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
392 MIMECONTF_MIME_LATEST,
393 "windows-1258", "windows-1258", "windows-1258" }
396 static const WCHAR asciiW[] = {'a','s','c','i','i',0};
398 static const MIME_CP_INFO western_cp[] =
400 { "IBM EBCDIC (US-Canada)",
401 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
402 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
403 "ibm037", "ibm037", "ibm037" },
404 { "OEM United States",
405 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
406 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
407 "ibm437", "ibm437", "ibm437" },
408 { "IBM EBCDIC (International)",
409 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
410 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
411 "ibm500", "ibm500", "ibm500" },
412 { "Western European (DOS)",
413 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
414 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
415 "ibm850", "ibm850", "ibm850" },
416 { "Portuguese (DOS)",
417 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
418 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
419 "ibm860", "ibm860", "ibm860" },
420 { "Icelandic (DOS)",
421 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
422 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
423 "ibm861", "ibm861", "ibm861" },
424 { "French Canadian (DOS)",
425 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
426 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
427 "ibm863", "ibm863", "ibm863" },
428 { "Nordic (DOS)",
429 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
430 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
431 "ibm865", "ibm865", "ibm865" },
432 { "Western European (Windows)",
433 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
434 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
435 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
436 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
437 "windows-1252", "windows-1252", "iso-8859-1" },
438 { "Western European (Mac)",
439 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
440 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
441 "macintosh", "macintosh", "macintosh" },
442 { "Icelandic (Mac)",
443 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
444 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
445 "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
446 { "US-ASCII",
447 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
448 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
449 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
450 "us-ascii", "us-ascii", "us-ascii", asciiW },
451 { "Western European (ISO)",
452 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
453 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
454 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
455 MIMECONTF_MIME_LATEST,
456 "iso-8859-1", "iso-8859-1", "iso-8859-1" },
457 { "Latin 9 (ISO)",
458 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
459 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
460 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
461 MIMECONTF_MIME_LATEST,
462 "iso-8859-15", "iso-8859-15", "iso-8859-15" }
464 static const MIME_CP_INFO unicode_cp[] =
466 { "Unicode",
467 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
468 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
469 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
470 MIMECONTF_MIME_LATEST,
471 "unicode", "unicode", "unicode" },
472 { "Unicode (UTF-7)",
473 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
474 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
475 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
476 "utf-7", "utf-7", "utf-7" },
477 { "Unicode (UTF-8)",
478 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
479 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
480 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
481 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
482 "utf-8", "utf-8", "utf-8" }
485 static const struct mlang_data
487 const char *description;
488 UINT family_codepage;
489 UINT number_of_cp;
490 const MIME_CP_INFO *mime_cp_info;
491 const char *fixed_font;
492 const char *proportional_font;
493 SCRIPT_ID sid;
494 } mlang_data[] =
496 { "Arabic",1256,sizeof(arabic_cp)/sizeof(arabic_cp[0]),arabic_cp,
497 "Courier","Arial", sidArabic }, /* FIXME */
498 { "Baltic",1257,sizeof(baltic_cp)/sizeof(baltic_cp[0]),baltic_cp,
499 "Courier","Arial", sidAsciiLatin }, /* FIXME */
500 { "Chinese Simplified",936,sizeof(chinese_simplified_cp)/sizeof(chinese_simplified_cp[0]),chinese_simplified_cp,
501 "Simsun","Simsun", sidHan },
502 { "Chinese Traditional",950,sizeof(chinese_traditional_cp)/sizeof(chinese_traditional_cp[0]),chinese_traditional_cp,
503 "MingLiu","New MingLiu", sidBopomofo },
504 { "Central European",1250,sizeof(central_european_cp)/sizeof(central_european_cp[0]),central_european_cp,
505 "Courier","Arial", sidAsciiLatin }, /* FIXME */
506 { "Cyrillic",1251,sizeof(cyrillic_cp)/sizeof(cyrillic_cp[0]),cyrillic_cp,
507 "Courier","Arial", sidCyrillic }, /* FIXME */
508 { "Greek",1253,sizeof(greek_cp)/sizeof(greek_cp[0]),greek_cp,
509 "Courier","Arial", sidGreek }, /* FIXME */
510 { "Hebrew",1255,sizeof(hebrew_cp)/sizeof(hebrew_cp[0]),hebrew_cp,
511 "Courier","Arial", sidHebrew }, /* FIXME */
512 { "Japanese",932,sizeof(japanese_cp)/sizeof(japanese_cp[0]),japanese_cp,
513 "MS Gothic","MS PGothic", sidKana },
514 { "Korean",949,sizeof(korean_cp)/sizeof(korean_cp[0]),korean_cp,
515 "Courier","Arial", sidHangul }, /* FIXME */
516 { "Thai",874,sizeof(thai_cp)/sizeof(thai_cp[0]),thai_cp,
517 "Courier","Arial", sidThai }, /* FIXME */
518 { "Turkish",1254,sizeof(turkish_cp)/sizeof(turkish_cp[0]),turkish_cp,
519 "Courier","Arial", sidAsciiLatin }, /* FIXME */
520 { "Vietnamese",1258,sizeof(vietnamese_cp)/sizeof(vietnamese_cp[0]),vietnamese_cp,
521 "Courier","Arial", sidAsciiLatin }, /* FIXME */
522 { "Western European",1252,sizeof(western_cp)/sizeof(western_cp[0]),western_cp,
523 "Courier","Arial", sidAsciiLatin }, /* FIXME */
524 { "Unicode",CP_UNICODE,sizeof(unicode_cp)/sizeof(unicode_cp[0]),unicode_cp,
525 "Courier","Arial" } /* FIXME */
528 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
530 static LONG dll_count;
533 * Japanese Detection and Conversion Functions
536 #define HANKATA(A) ((A >= 161) && (A <= 223))
537 #define ISEUC(A) ((A >= 161) && (A <= 254))
538 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
539 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
540 #define SJIS2(A) ((A >= 64) && (A <= 252))
541 #define ISMARU(A) ((A >= 202) && (A <= 206))
542 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
544 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
546 UINT code = 0;
547 DWORD i = 0;
548 unsigned char c1,c2;
550 while ((code == 0 || code == 51932) && i < count)
552 c1 = input[i];
553 if (c1 == 0x1b /* ESC */)
555 i++;
556 if (i >= count)
557 return code;
558 c1 = input[i];
559 if (c1 == '$')
561 i++;
562 if (i >= count)
563 return code;
564 c1 = input[i];
565 if (c1 =='B' || c1 == '@')
566 code = 50220;
568 if (c1 == 'K')
569 code = 50220;
571 else if (c1 >= 129)
573 i++;
574 if (i >= count)
575 return code;
576 c2 = input[i];
577 if NOTEUC(c1,c2)
578 code = 932;
579 else if (ISEUC(c1) && ISEUC(c2))
580 code = 51932;
581 else if (((c1 == 142)) && HANKATA(c2))
582 code = 51932;
584 i++;
586 return code;
589 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
591 unsigned char c1 = *p1;
592 unsigned char c2 = *p2;
593 int row = c1 < 95 ? 112 : 176;
594 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
596 *p1 = ((c1 + 1) >> 1) + row;
597 *p2 = c2 + cell;
600 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
602 unsigned char c1 = *p1;
603 unsigned char c2 = *p2;
604 int shift = c2 < 159;
605 int row = c1 < 160 ? 112 : 176;
606 int cell = shift ? (31 + (c2 > 127)): 126;
608 *p1 = ((c1 - row) << 1) - shift;
609 *p2 -= cell;
612 static int han2zen(unsigned char *p1, unsigned char *p2)
614 BOOL maru = FALSE;
615 BOOL nigori = FALSE;
616 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
617 131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
618 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
619 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
620 131,129,129 };
621 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
622 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
623 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
624 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
626 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
627 nigori = TRUE;
628 else if ((*p2 == 223) && (ISMARU(*p1)))
629 maru = TRUE;
631 if (*p1 >= 161 && *p1 <= 223)
633 unsigned char index = *p1 - 161;
634 *p1 = char1[index];
635 *p2 = char2[index];
638 if (maru || nigori)
640 if (nigori)
642 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
643 (*p2)++;
644 else if ((*p1 == 131) && (*p2 == 69))
645 *p2 = 148;
647 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
648 *p2+= 2;
650 return 1;
653 return 0;
657 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
659 DWORD i = 0;
660 int j = 0;
661 unsigned char p2,p;
662 BOOL shifted = FALSE;
664 while (i < count)
666 p = input[i];
667 if (p == 0x1b /* ESC */)
669 i++;
670 if (i >= count)
671 return 0;
672 p2 = input[i];
673 if (p2 == '$' || p2 =='(')
674 i++;
675 if (p2 == 'K' || p2 =='$')
676 shifted = TRUE;
677 else
678 shifted = FALSE;
680 else
682 if (shifted)
684 i++;
685 if (i >= count)
686 return 0;
687 p2 = input[i];
688 jis2sjis(&p,&p2);
689 output[j++]=p;
690 output[j++]=p2;
692 else
694 output[j++] = p;
697 i++;
699 return j;
702 static inline int exit_shift(LPSTR out, int c)
704 if (out)
706 out[c] = 0x1b;
707 out[c+1] = '(';
708 out[c+2] = 'B';
710 return 3;
713 static inline int enter_shift(LPSTR out, int c)
715 if (out)
717 out[c] = 0x1b;
718 out[c+1] = '$';
719 out[c+2] = 'B';
721 return 3;
725 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
727 DWORD i = 0;
728 int j = 0;
729 unsigned char p2,p;
730 BOOL shifted = FALSE;
732 while (i < count)
734 p = input[i] & 0xff;
735 if (p == 10 || p == 13) /* NL and CR */
737 if (shifted)
739 shifted = FALSE;
740 j += exit_shift(output,j);
742 if (output)
743 output[j++] = p;
744 else
745 j++;
747 else
749 if (SJIS1(p))
751 i++;
752 if (i >= count)
753 return 0;
754 p2 = input[i] & 0xff;
755 if (SJIS2(p2))
757 sjis2jis(&p,&p2);
758 if (!shifted)
760 shifted = TRUE;
761 j+=enter_shift(output,j);
765 if (output)
767 output[j++]=p;
768 output[j++]=p2;
770 else
771 j+=2;
773 else
775 if (HANKATA(p))
777 if ((i+1) >= count)
778 return 0;
779 p2 = input[i+1] & 0xff;
780 i+=han2zen(&p,&p2);
781 sjis2jis(&p,&p2);
782 if (!shifted)
784 shifted = TRUE;
785 j+=enter_shift(output,j);
787 if (output)
789 output[j++]=p;
790 output[j++]=p2;
792 else
793 j+=2;
795 else
797 if (shifted)
799 shifted = FALSE;
800 j += exit_shift(output,j);
802 if (output)
803 output[j++]=p;
804 else
805 j++;
809 i++;
811 if (shifted)
812 j += exit_shift(output,j);
813 return j;
816 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
817 LPWSTR output, DWORD out_count)
819 CHAR *sjis_string;
820 UINT rc = 0;
821 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
822 rc = ConvertJIS2SJIS(input,count,sjis_string);
823 if (rc)
825 TRACE("%s\n",debugstr_an(sjis_string,rc));
826 if (output)
827 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
828 else
829 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
831 HeapFree(GetProcessHeap(),0,sjis_string);
832 return rc;
836 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
837 LPWSTR output, DWORD out_count)
839 CHAR *sjis_string;
840 UINT rc = 0;
841 int code = DetectJapaneseCode(input,count);
842 TRACE("Japanese code %i\n",code);
844 switch (code)
846 case 0:
847 if (output)
848 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
849 else
850 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
851 break;
853 case 932:
854 if (output)
855 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
856 else
857 rc = MultiByteToWideChar(932,0,input,count,0,0);
858 break;
860 case 51932:
861 if (output)
862 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
863 else
864 rc = MultiByteToWideChar(20932,0,input,count,0,0);
865 break;
867 case 50220:
868 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
869 rc = ConvertJIS2SJIS(input,count,sjis_string);
870 if (rc)
872 TRACE("%s\n",debugstr_an(sjis_string,rc));
873 if (output)
874 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
875 else
876 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
878 HeapFree(GetProcessHeap(),0,sjis_string);
879 break;
881 return rc;
884 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
885 LPSTR output, DWORD out_count)
887 CHAR *sjis_string;
888 INT len;
889 UINT rc = 0;
891 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
892 sjis_string = HeapAlloc(GetProcessHeap(),0,len);
893 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
894 TRACE("%s\n",debugstr_an(sjis_string,len));
896 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
897 if (out_count >= rc)
899 ConvertSJIS2JIS(sjis_string, len, output);
901 HeapFree(GetProcessHeap(),0,sjis_string);
902 return rc;
907 * Dll lifetime tracking declaration
909 static void LockModule(void)
911 InterlockedIncrement(&dll_count);
914 static void UnlockModule(void)
916 InterlockedDecrement(&dll_count);
919 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
921 switch(fdwReason) {
922 case DLL_PROCESS_ATTACH:
923 instance = hInstDLL;
924 MLANG_tls_index = TlsAlloc();
925 DisableThreadLibraryCalls(hInstDLL);
926 break;
927 case DLL_PROCESS_DETACH:
928 if (lpv) break;
929 TlsFree(MLANG_tls_index);
930 break;
932 return TRUE;
935 HRESULT WINAPI ConvertINetMultiByteToUnicode(
936 LPDWORD pdwMode,
937 DWORD dwEncoding,
938 LPCSTR pSrcStr,
939 LPINT pcSrcSize,
940 LPWSTR pDstStr,
941 LPINT pcDstSize)
943 INT src_len = -1;
945 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
946 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
948 if (!pcDstSize)
949 return E_FAIL;
951 if (!pcSrcSize)
952 pcSrcSize = &src_len;
954 if (!*pcSrcSize)
956 *pcDstSize = 0;
957 return S_OK;
960 /* forwarding euc-jp to EUC-JP */
961 if (dwEncoding == 51932)
962 dwEncoding = 20932;
964 switch (dwEncoding)
966 case CP_UNICODE:
967 if (*pcSrcSize == -1)
968 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
969 *pcDstSize = min(*pcSrcSize, *pcDstSize);
970 *pcSrcSize *= sizeof(WCHAR);
971 if (pDstStr)
972 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
973 break;
975 case 50220:
976 case 50221:
977 case 50222:
978 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
979 break;
980 case 50932:
981 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
982 break;
984 default:
985 if (*pcSrcSize == -1)
986 *pcSrcSize = lstrlenA(pSrcStr);
988 if (pDstStr)
989 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
990 else
991 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
992 break;
995 if (!*pcDstSize)
996 return E_FAIL;
998 return S_OK;
1001 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
1002 LPDWORD pdwMode,
1003 DWORD dwEncoding,
1004 LPCWSTR pSrcStr,
1005 LPINT pcSrcSize,
1006 LPSTR pDstStr,
1007 LPINT pcDstSize)
1009 INT destsz, size;
1010 INT src_len = -1;
1012 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
1013 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1015 if (!pcDstSize)
1016 return S_OK;
1018 if (!pcSrcSize)
1019 pcSrcSize = &src_len;
1021 destsz = (pDstStr) ? *pcDstSize : 0;
1022 *pcDstSize = 0;
1024 if (!pSrcStr || !*pcSrcSize)
1025 return S_OK;
1027 if (*pcSrcSize == -1)
1028 *pcSrcSize = lstrlenW(pSrcStr);
1030 /* forwarding euc-jp to EUC-JP */
1031 if (dwEncoding == 51932)
1032 dwEncoding = 20932;
1034 if (dwEncoding == CP_UNICODE)
1036 if (*pcSrcSize == -1)
1037 *pcSrcSize = lstrlenW(pSrcStr);
1039 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1040 if (pDstStr)
1041 memmove(pDstStr, pSrcStr, size);
1043 if (size >= destsz)
1044 goto fail;
1046 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1048 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1049 if (!size)
1050 goto fail;
1052 if (pDstStr)
1054 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1055 destsz);
1056 if (!size)
1057 goto fail;
1061 else
1063 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1064 NULL, 0, NULL, NULL);
1065 if (!size)
1066 goto fail;
1068 if (pDstStr)
1070 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1071 pDstStr, destsz, NULL, NULL);
1072 if (!size)
1073 goto fail;
1077 *pcDstSize = size;
1078 return S_OK;
1080 fail:
1081 *pcSrcSize = 0;
1082 *pcDstSize = 0;
1083 return E_FAIL;
1086 HRESULT WINAPI ConvertINetString(
1087 LPDWORD pdwMode,
1088 DWORD dwSrcEncoding,
1089 DWORD dwDstEncoding,
1090 LPCSTR pSrcStr,
1091 LPINT pcSrcSize,
1092 LPSTR pDstStr,
1093 LPINT pcDstSize
1096 TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1097 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1099 if (dwSrcEncoding == CP_UNICODE)
1101 INT cSrcSizeW;
1102 if (pcSrcSize && *pcSrcSize != -1)
1104 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1105 pcSrcSize = &cSrcSizeW;
1107 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1109 else if (dwDstEncoding == CP_UNICODE)
1111 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1112 *pcDstSize *= sizeof(WCHAR);
1113 return hr;
1115 else
1117 INT cDstSizeW;
1118 LPWSTR pDstStrW;
1119 HRESULT hr;
1121 TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1123 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1124 if (hr != S_OK)
1125 return hr;
1127 pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1128 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1129 if (hr == S_OK)
1130 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1132 HeapFree(GetProcessHeap(), 0, pDstStrW);
1133 return hr;
1137 static HRESULT GetFamilyCodePage(
1138 UINT uiCodePage,
1139 UINT* puiFamilyCodePage)
1141 UINT i, n;
1143 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1145 if (!puiFamilyCodePage) return S_FALSE;
1147 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1149 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1151 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1153 *puiFamilyCodePage = mlang_data[i].family_codepage;
1154 return S_OK;
1159 return S_FALSE;
1162 HRESULT WINAPI IsConvertINetStringAvailable(
1163 DWORD dwSrcEncoding,
1164 DWORD dwDstEncoding)
1166 UINT src_family, dst_family;
1168 TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
1170 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1171 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1172 return S_FALSE;
1174 if (src_family == dst_family) return S_OK;
1176 /* we can convert any codepage to/from unicode */
1177 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1179 return S_FALSE;
1182 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1184 CHAR buffer[MAX_RFC1766_NAME];
1185 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1186 INT i;
1188 if (n)
1190 i = PRIMARYLANGID(lcid);
1191 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1192 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1193 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1195 buffer[n - 1] = '-';
1196 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1197 if (!i)
1198 buffer[n - 1] = '\0';
1200 else
1201 i = 0;
1203 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1204 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1206 return E_FAIL;
1209 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1211 WCHAR buffer[MAX_RFC1766_NAME];
1212 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1213 INT i;
1215 if (n)
1217 i = PRIMARYLANGID(lcid);
1218 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1219 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1220 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1222 buffer[n - 1] = '-';
1223 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1224 if (!i)
1225 buffer[n - 1] = '\0';
1227 else
1228 i = 0;
1230 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1231 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1233 return E_FAIL;
1236 HRESULT WINAPI LcidToRfc1766A(
1237 LCID lcid,
1238 LPSTR pszRfc1766,
1239 INT nChar)
1241 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1242 if (!pszRfc1766)
1243 return E_INVALIDARG;
1245 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1248 HRESULT WINAPI LcidToRfc1766W(
1249 LCID lcid,
1250 LPWSTR pszRfc1766,
1251 INT nChar)
1253 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1254 if (!pszRfc1766)
1255 return E_INVALIDARG;
1257 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1260 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1262 RFC1766INFO info;
1263 ULONG num;
1265 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1267 if (!strcmpiW(info.wszRfc1766, rfc1766))
1269 *lcid = info.lcid;
1270 return S_OK;
1272 if (strlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1274 *lcid = PRIMARYLANGID(info.lcid);
1275 return S_OK;
1279 return E_FAIL;
1282 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1284 IEnumRfc1766 *enumrfc1766;
1285 HRESULT hr;
1287 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1289 if (!pLocale || !pszRfc1766)
1290 return E_INVALIDARG;
1292 hr = EnumRfc1766_create(0, &enumrfc1766);
1293 if (FAILED(hr))
1294 return hr;
1296 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1297 IEnumRfc1766_Release(enumrfc1766);
1299 return hr;
1302 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1304 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1306 if (!rfc1766A)
1307 return E_INVALIDARG;
1309 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1310 rfc1766W[MAX_RFC1766_NAME] = 0;
1312 return Rfc1766ToLcidW(lcid, rfc1766W);
1315 /******************************************************************************
1316 * MLANG ClassFactory
1318 typedef struct {
1319 IClassFactory IClassFactory_iface;
1320 LONG ref;
1321 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1322 } IClassFactoryImpl;
1324 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1326 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1329 struct object_creation_info
1331 const CLSID *clsid;
1332 LPCSTR szClassName;
1333 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1336 static const struct object_creation_info object_creation[] =
1338 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1339 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1342 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1344 TRACE("%s\n", debugstr_guid(riid) );
1346 if (IsEqualGUID(riid, &IID_IUnknown)
1347 || IsEqualGUID(riid, &IID_IClassFactory))
1349 IClassFactory_AddRef(iface);
1350 *ppobj = iface;
1351 return S_OK;
1354 *ppobj = NULL;
1355 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1356 return E_NOINTERFACE;
1359 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1361 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1362 return InterlockedIncrement(&This->ref);
1365 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1367 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1368 ULONG ref = InterlockedDecrement(&This->ref);
1370 if (ref == 0)
1372 TRACE("Destroying %p\n", This);
1373 HeapFree(GetProcessHeap(), 0, This);
1376 return ref;
1379 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1380 REFIID riid, void **ppobj)
1382 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1383 HRESULT hres;
1384 LPUNKNOWN punk;
1386 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1388 *ppobj = NULL;
1389 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1390 if (SUCCEEDED(hres)) {
1391 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1392 IUnknown_Release(punk);
1394 TRACE("returning (%p) -> %x\n", *ppobj, hres);
1395 return hres;
1398 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1400 if (dolock)
1401 LockModule();
1402 else
1403 UnlockModule();
1405 return S_OK;
1408 static const IClassFactoryVtbl MLANGCF_Vtbl =
1410 MLANGCF_QueryInterface,
1411 MLANGCF_AddRef,
1412 MLANGCF_Release,
1413 MLANGCF_CreateInstance,
1414 MLANGCF_LockServer
1417 /******************************************************************
1418 * DllGetClassObject (MLANG.@)
1420 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1422 unsigned int i;
1423 IClassFactoryImpl *factory;
1425 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1427 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1428 && ! IsEqualGUID( &IID_IUnknown, iid) )
1429 return E_NOINTERFACE;
1431 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
1433 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1434 break;
1437 if (i == sizeof(object_creation)/sizeof(object_creation[0]))
1439 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1440 return CLASS_E_CLASSNOTAVAILABLE;
1443 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1445 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1446 if (factory == NULL) return E_OUTOFMEMORY;
1448 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1449 factory->ref = 1;
1451 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1453 *ppv = &factory->IClassFactory_iface;
1455 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1457 return S_OK;
1461 /******************************************************************************/
1463 typedef struct tagMLang_impl
1465 IMLangFontLink IMLangFontLink_iface;
1466 IMultiLanguage IMultiLanguage_iface;
1467 IMultiLanguage3 IMultiLanguage3_iface;
1468 IMLangFontLink2 IMLangFontLink2_iface;
1469 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1470 LONG ref;
1471 DWORD total_cp, total_scripts;
1472 } MLang_impl;
1474 /******************************************************************************/
1476 typedef struct tagEnumCodePage_impl
1478 IEnumCodePage IEnumCodePage_iface;
1479 LONG ref;
1480 MIMECPINFO *cpinfo;
1481 DWORD total, pos;
1482 } EnumCodePage_impl;
1484 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1486 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1489 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1490 IEnumCodePage* iface,
1491 REFIID riid,
1492 void** ppvObject)
1494 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1496 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1498 if (IsEqualGUID(riid, &IID_IUnknown)
1499 || IsEqualGUID(riid, &IID_IEnumCodePage))
1501 IEnumCodePage_AddRef(iface);
1502 TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
1503 *ppvObject = &This->IEnumCodePage_iface;
1504 return S_OK;
1507 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1508 return E_NOINTERFACE;
1511 static ULONG WINAPI fnIEnumCodePage_AddRef(
1512 IEnumCodePage* iface)
1514 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1515 return InterlockedIncrement(&This->ref);
1518 static ULONG WINAPI fnIEnumCodePage_Release(
1519 IEnumCodePage* iface)
1521 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1522 ULONG ref = InterlockedDecrement(&This->ref);
1524 TRACE("%p ref = %d\n", This, ref);
1525 if (ref == 0)
1527 TRACE("Destroying %p\n", This);
1528 HeapFree(GetProcessHeap(), 0, This->cpinfo);
1529 HeapFree(GetProcessHeap(), 0, This);
1532 return ref;
1535 static HRESULT WINAPI fnIEnumCodePage_Clone(
1536 IEnumCodePage* iface,
1537 IEnumCodePage** ppEnum)
1539 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1540 FIXME("%p %p\n", This, ppEnum);
1541 return E_NOTIMPL;
1544 static HRESULT WINAPI fnIEnumCodePage_Next(
1545 IEnumCodePage* iface,
1546 ULONG celt,
1547 PMIMECPINFO rgelt,
1548 ULONG* pceltFetched)
1550 ULONG i;
1551 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1553 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1555 if (!pceltFetched) return S_FALSE;
1556 *pceltFetched = 0;
1558 if (!rgelt) return S_FALSE;
1560 if (This->pos + celt > This->total)
1561 celt = This->total - This->pos;
1563 if (!celt) return S_FALSE;
1565 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1566 *pceltFetched = celt;
1567 This->pos += celt;
1569 for (i = 0; i < celt; i++)
1571 TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
1572 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1573 rgelt[i].uiFamilyCodePage,
1574 wine_dbgstr_w(rgelt[i].wszDescription),
1575 wine_dbgstr_w(rgelt[i].wszWebCharset),
1576 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1577 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1578 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1579 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1580 rgelt[i].bGDICharset);
1582 return S_OK;
1585 static HRESULT WINAPI fnIEnumCodePage_Reset(
1586 IEnumCodePage* iface)
1588 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1590 TRACE("%p\n", This);
1592 This->pos = 0;
1593 return S_OK;
1596 static HRESULT WINAPI fnIEnumCodePage_Skip(
1597 IEnumCodePage* iface,
1598 ULONG celt)
1600 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1602 TRACE("%p %u\n", This, celt);
1604 if (celt >= This->total) return S_FALSE;
1606 This->pos += celt;
1607 return S_OK;
1610 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1612 fnIEnumCodePage_QueryInterface,
1613 fnIEnumCodePage_AddRef,
1614 fnIEnumCodePage_Release,
1615 fnIEnumCodePage_Clone,
1616 fnIEnumCodePage_Next,
1617 fnIEnumCodePage_Reset,
1618 fnIEnumCodePage_Skip
1621 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1622 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1624 EnumCodePage_impl *ecp;
1625 MIMECPINFO *cpinfo;
1626 UINT i, n;
1628 TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1630 if (!grfFlags) /* enumerate internal data base of encodings */
1631 grfFlags = MIMECONTF_MIME_LATEST;
1633 ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1634 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1635 ecp->ref = 1;
1636 ecp->pos = 0;
1637 ecp->total = 0;
1638 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1640 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1642 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1643 ecp->total++;
1647 ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1648 sizeof(MIMECPINFO) * ecp->total);
1649 cpinfo = ecp->cpinfo;
1651 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1653 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1655 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1656 fill_cp_info(&mlang_data[i], n, cpinfo++);
1660 TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
1662 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1664 return S_OK;
1667 /******************************************************************************/
1669 typedef struct tagEnumScript_impl
1671 IEnumScript IEnumScript_iface;
1672 LONG ref;
1673 SCRIPTINFO *script_info;
1674 DWORD total, pos;
1675 } EnumScript_impl;
1677 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1679 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1682 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1683 IEnumScript* iface,
1684 REFIID riid,
1685 void** ppvObject)
1687 EnumScript_impl *This = impl_from_IEnumScript( iface );
1689 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1691 if (IsEqualGUID(riid, &IID_IUnknown)
1692 || IsEqualGUID(riid, &IID_IEnumScript))
1694 IEnumScript_AddRef(iface);
1695 TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
1696 *ppvObject = &This->IEnumScript_iface;
1697 return S_OK;
1700 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1701 return E_NOINTERFACE;
1704 static ULONG WINAPI fnIEnumScript_AddRef(
1705 IEnumScript* iface)
1707 EnumScript_impl *This = impl_from_IEnumScript( iface );
1708 return InterlockedIncrement(&This->ref);
1711 static ULONG WINAPI fnIEnumScript_Release(
1712 IEnumScript* iface)
1714 EnumScript_impl *This = impl_from_IEnumScript( iface );
1715 ULONG ref = InterlockedDecrement(&This->ref);
1717 TRACE("%p ref = %d\n", This, ref);
1718 if (ref == 0)
1720 TRACE("Destroying %p\n", This);
1721 HeapFree(GetProcessHeap(), 0, This->script_info);
1722 HeapFree(GetProcessHeap(), 0, This);
1725 return ref;
1728 static HRESULT WINAPI fnIEnumScript_Clone(
1729 IEnumScript* iface,
1730 IEnumScript** ppEnum)
1732 EnumScript_impl *This = impl_from_IEnumScript( iface );
1733 FIXME("%p %p: stub!\n", This, ppEnum);
1734 return E_NOTIMPL;
1737 static HRESULT WINAPI fnIEnumScript_Next(
1738 IEnumScript* iface,
1739 ULONG celt,
1740 PSCRIPTINFO rgelt,
1741 ULONG* pceltFetched)
1743 EnumScript_impl *This = impl_from_IEnumScript( iface );
1745 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1747 if (!pceltFetched || !rgelt) return E_FAIL;
1749 *pceltFetched = 0;
1751 if (This->pos + celt > This->total)
1752 celt = This->total - This->pos;
1754 if (!celt) return S_FALSE;
1756 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1757 *pceltFetched = celt;
1758 This->pos += celt;
1760 return S_OK;
1763 static HRESULT WINAPI fnIEnumScript_Reset(
1764 IEnumScript* iface)
1766 EnumScript_impl *This = impl_from_IEnumScript( iface );
1768 TRACE("%p\n", This);
1770 This->pos = 0;
1771 return S_OK;
1774 static HRESULT WINAPI fnIEnumScript_Skip(
1775 IEnumScript* iface,
1776 ULONG celt)
1778 EnumScript_impl *This = impl_from_IEnumScript( iface );
1780 TRACE("%p %u\n", This, celt);
1782 if (celt >= This->total) return S_FALSE;
1784 This->pos += celt;
1785 return S_OK;
1788 static const IEnumScriptVtbl IEnumScript_vtbl =
1790 fnIEnumScript_QueryInterface,
1791 fnIEnumScript_AddRef,
1792 fnIEnumScript_Release,
1793 fnIEnumScript_Clone,
1794 fnIEnumScript_Next,
1795 fnIEnumScript_Reset,
1796 fnIEnumScript_Skip
1799 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1800 LANGID LangId, IEnumScript** ppEnumScript )
1802 EnumScript_impl *es;
1803 UINT i;
1805 TRACE("%p, %08x, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1807 if (!dwFlags) /* enumerate all available scripts */
1808 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1810 es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1811 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1812 es->ref = 1;
1813 es->pos = 0;
1814 /* do not enumerate unicode flavours */
1815 es->total = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
1816 es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1818 for (i = 0; i < es->total; i++)
1820 es->script_info[i].ScriptId = i;
1821 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1822 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1823 es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1824 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1825 es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1826 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1827 es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1830 TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
1832 *ppEnumScript = &es->IEnumScript_iface;
1834 return S_OK;
1837 /******************************************************************************/
1839 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1841 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1844 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1845 IMLangFontLink* iface,
1846 REFIID riid,
1847 void** ppvObject)
1849 MLang_impl *This = impl_from_IMLangFontLink( iface );
1850 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1853 static ULONG WINAPI fnIMLangFontLink_AddRef(
1854 IMLangFontLink* iface)
1856 MLang_impl *This = impl_from_IMLangFontLink( iface );
1857 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1860 static ULONG WINAPI fnIMLangFontLink_Release(
1861 IMLangFontLink* iface)
1863 MLang_impl *This = impl_from_IMLangFontLink( iface );
1864 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1867 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1868 IMLangFontLink* iface,
1869 WCHAR ch_src,
1870 DWORD* codepages)
1872 MLang_impl *This = impl_from_IMLangFontLink( iface );
1873 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
1876 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
1877 IMLangFontLink* iface,
1878 const WCHAR* src,
1879 LONG src_len,
1880 DWORD priority_cp,
1881 DWORD* codepages,
1882 LONG* ret_len)
1884 MLang_impl *This = impl_from_IMLangFontLink( iface );
1885 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
1886 codepages, ret_len);
1889 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
1890 IMLangFontLink* iface,
1891 UINT codepage,
1892 DWORD* codepages)
1894 MLang_impl *This = impl_from_IMLangFontLink( iface );
1895 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
1898 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
1899 IMLangFontLink* iface,
1900 DWORD codepages,
1901 UINT def_codepage,
1902 UINT* codepage)
1904 MLang_impl *This = impl_from_IMLangFontLink(iface);
1905 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
1906 def_codepage, codepage);
1909 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
1910 IMLangFontLink* iface,
1911 HDC hdc,
1912 HFONT hfont,
1913 DWORD* codepages)
1915 MLang_impl *This = impl_from_IMLangFontLink(iface);
1916 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
1919 static HRESULT WINAPI fnIMLangFontLink_MapFont(
1920 IMLangFontLink* iface,
1921 HDC hDC,
1922 DWORD dwCodePages,
1923 HFONT hSrcFont,
1924 HFONT* phDestFont)
1926 FIXME("\n");
1927 return E_NOTIMPL;
1930 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
1931 IMLangFontLink* iface,
1932 HFONT hFont)
1934 FIXME("\n");
1935 return E_NOTIMPL;
1938 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
1939 IMLangFontLink* iface)
1941 FIXME("\n");
1942 return E_NOTIMPL;
1946 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
1948 fnIMLangFontLink_QueryInterface,
1949 fnIMLangFontLink_AddRef,
1950 fnIMLangFontLink_Release,
1951 fnIMLangFontLink_GetCharCodePages,
1952 fnIMLangFontLink_GetStrCodePages,
1953 fnIMLangFontLink_CodePageToCodePages,
1954 fnIMLangFontLink_CodePagesToCodePage,
1955 fnIMLangFontLink_GetFontCodePages,
1956 fnIMLangFontLink_MapFont,
1957 fnIMLangFontLink_ReleaseFont,
1958 fnIMLangFontLink_ResetFontMapping,
1961 /******************************************************************************/
1963 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
1965 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
1968 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
1969 IMultiLanguage* iface,
1970 REFIID riid,
1971 void** obj)
1973 MLang_impl *This = impl_from_IMultiLanguage( iface );
1974 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
1977 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
1979 MLang_impl *This = impl_from_IMultiLanguage( iface );
1980 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
1983 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
1985 MLang_impl *This = impl_from_IMultiLanguage( iface );
1986 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
1989 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
1990 IMultiLanguage* iface,
1991 UINT* cp)
1993 MLang_impl *This = impl_from_IMultiLanguage( iface );
1994 TRACE("(%p, %p)\n", This, cp);
1995 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
1998 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
1999 IMultiLanguage* iface,
2000 UINT uiCodePage,
2001 PMIMECPINFO pCodePageInfo)
2003 UINT i, n;
2004 MLang_impl *This = impl_from_IMultiLanguage( iface );
2006 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
2008 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2010 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2012 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2014 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2015 return S_OK;
2020 return S_FALSE;
2023 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
2024 IMultiLanguage* iface,
2025 UINT cp,
2026 UINT* family_cp)
2028 MLang_impl *This = impl_from_IMultiLanguage( iface );
2029 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2032 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2033 IMultiLanguage* iface,
2034 DWORD grfFlags,
2035 IEnumCodePage** ppEnumCodePage)
2037 MLang_impl *This = impl_from_IMultiLanguage( iface );
2039 TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
2041 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2044 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2045 IMultiLanguage* iface,
2046 BSTR Charset,
2047 PMIMECSETINFO pCharsetInfo)
2049 MLang_impl *This = impl_from_IMultiLanguage( iface );
2050 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2053 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2054 IMultiLanguage* iface,
2055 DWORD src_enc,
2056 DWORD dst_enc)
2058 MLang_impl *This = impl_from_IMultiLanguage( iface );
2059 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2062 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2063 IMultiLanguage* iface,
2064 DWORD* mode,
2065 DWORD src_enc,
2066 DWORD dst_enc,
2067 BYTE* src,
2068 UINT* src_size,
2069 BYTE* dest,
2070 UINT* dest_size)
2072 MLang_impl *This = impl_from_IMultiLanguage( iface );
2073 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2074 dst_enc, src, src_size, dest, dest_size);
2077 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2078 IMultiLanguage* iface,
2079 DWORD* mode,
2080 DWORD src_enc,
2081 CHAR* src,
2082 UINT* src_size,
2083 WCHAR* dest,
2084 UINT* dest_size)
2086 MLang_impl *This = impl_from_IMultiLanguage( iface );
2087 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2088 mode, src_enc, src, src_size, dest, dest_size);
2091 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2092 IMultiLanguage* iface,
2093 DWORD* mode,
2094 DWORD encoding,
2095 WCHAR* src,
2096 UINT* src_size,
2097 CHAR* dest,
2098 UINT* dest_size)
2100 MLang_impl *This = impl_from_IMultiLanguage(iface);
2101 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2102 mode, encoding, src, src_size, dest, dest_size);
2105 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2106 IMultiLanguage* iface)
2108 MLang_impl *This = impl_from_IMultiLanguage( iface );
2109 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2112 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2113 IMultiLanguage* iface,
2114 LCID lcid,
2115 BSTR* pbstrRfc1766)
2117 MLang_impl *This = impl_from_IMultiLanguage(iface);
2118 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2121 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2122 IMultiLanguage* iface,
2123 LCID* locale,
2124 BSTR rfc1766)
2126 MLang_impl *This = impl_from_IMultiLanguage(iface);
2127 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2130 /******************************************************************************/
2132 typedef struct tagEnumRfc1766_impl
2134 IEnumRfc1766 IEnumRfc1766_iface;
2135 LONG ref;
2136 RFC1766INFO *info;
2137 DWORD total, pos;
2138 } EnumRfc1766_impl;
2140 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2142 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2145 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2146 IEnumRfc1766 *iface,
2147 REFIID riid,
2148 void** ppvObject)
2150 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2152 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2154 if (IsEqualGUID(riid, &IID_IUnknown)
2155 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2157 IEnumRfc1766_AddRef(iface);
2158 TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
2159 *ppvObject = &This->IEnumRfc1766_iface;
2160 return S_OK;
2163 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2164 return E_NOINTERFACE;
2167 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2168 IEnumRfc1766 *iface)
2170 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2171 return InterlockedIncrement(&This->ref);
2174 static ULONG WINAPI fnIEnumRfc1766_Release(
2175 IEnumRfc1766 *iface)
2177 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2178 ULONG ref = InterlockedDecrement(&This->ref);
2180 TRACE("%p ref = %d\n", This, ref);
2181 if (ref == 0)
2183 TRACE("Destroying %p\n", This);
2184 HeapFree(GetProcessHeap(), 0, This->info);
2185 HeapFree(GetProcessHeap(), 0, This);
2187 return ref;
2190 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2191 IEnumRfc1766 *iface,
2192 IEnumRfc1766 **ppEnum)
2194 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2196 FIXME("%p %p\n", This, ppEnum);
2197 return E_NOTIMPL;
2200 static HRESULT WINAPI fnIEnumRfc1766_Next(
2201 IEnumRfc1766 *iface,
2202 ULONG celt,
2203 PRFC1766INFO rgelt,
2204 ULONG *pceltFetched)
2206 ULONG i;
2207 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2209 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
2211 if (!pceltFetched) return S_FALSE;
2212 *pceltFetched = 0;
2214 if (!rgelt) return S_FALSE;
2216 if (This->pos + celt > This->total)
2217 celt = This->total - This->pos;
2219 if (!celt) return S_FALSE;
2221 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2222 *pceltFetched = celt;
2223 This->pos += celt;
2225 for (i = 0; i < celt; i++)
2227 TRACE("#%u: %08x %s %s\n",
2228 i, rgelt[i].lcid,
2229 wine_dbgstr_w(rgelt[i].wszRfc1766),
2230 wine_dbgstr_w(rgelt[i].wszLocaleName));
2232 return S_OK;
2235 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2236 IEnumRfc1766 *iface)
2238 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2240 TRACE("%p\n", This);
2242 This->pos = 0;
2243 return S_OK;
2246 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2247 IEnumRfc1766 *iface,
2248 ULONG celt)
2250 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2252 TRACE("%p %u\n", This, celt);
2254 if (celt >= This->total) return S_FALSE;
2256 This->pos += celt;
2257 return S_OK;
2260 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2262 fnIEnumRfc1766_QueryInterface,
2263 fnIEnumRfc1766_AddRef,
2264 fnIEnumRfc1766_Release,
2265 fnIEnumRfc1766_Clone,
2266 fnIEnumRfc1766_Next,
2267 fnIEnumRfc1766_Reset,
2268 fnIEnumRfc1766_Skip
2271 struct enum_locales_data
2273 RFC1766INFO *info;
2274 DWORD total, allocated;
2277 static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
2279 WCHAR *end;
2280 struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
2281 RFC1766INFO *info;
2283 TRACE("%s\n", debugstr_w(locale));
2285 if (data->total >= data->allocated)
2287 data->allocated += 32;
2288 data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2289 if (!data->info) return FALSE;
2292 info = &data->info[data->total];
2294 info->lcid = strtolW(locale, &end, 16);
2295 if (*end) /* invalid number */
2296 return FALSE;
2298 info->wszRfc1766[0] = 0;
2299 lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
2301 info->wszLocaleName[0] = 0;
2302 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2303 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2305 data->total++;
2307 return TRUE;
2310 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2312 EnumRfc1766_impl *rfc;
2313 struct enum_locales_data data;
2315 TRACE("%04x, %p\n", LangId, ppEnum);
2317 rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2318 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2319 rfc->ref = 1;
2320 rfc->pos = 0;
2321 rfc->total = 0;
2323 data.total = 0;
2324 data.allocated = 160;
2325 data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2326 if (!data.info)
2328 HeapFree(GetProcessHeap(), 0, rfc);
2329 return E_OUTOFMEMORY;
2332 TlsSetValue(MLANG_tls_index, &data);
2333 EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
2334 TlsSetValue(MLANG_tls_index, NULL);
2336 TRACE("enumerated %d rfc1766 structures\n", data.total);
2338 if (!data.total)
2340 HeapFree(GetProcessHeap(), 0, data.info);
2341 HeapFree(GetProcessHeap(), 0, rfc);
2342 return E_FAIL;
2345 rfc->info = data.info;
2346 rfc->total = data.total;
2348 *ppEnum = &rfc->IEnumRfc1766_iface;
2349 return S_OK;
2352 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2353 IMultiLanguage *iface,
2354 IEnumRfc1766 **ppEnumRfc1766)
2356 MLang_impl *This = impl_from_IMultiLanguage( iface );
2358 TRACE("%p %p\n", This, ppEnumRfc1766);
2360 return EnumRfc1766_create(0, ppEnumRfc1766);
2363 /******************************************************************************/
2365 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2366 IMultiLanguage* iface,
2367 LCID Locale,
2368 PRFC1766INFO pRfc1766Info)
2370 LCTYPE type = LOCALE_SLANGUAGE;
2372 TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
2374 if (!pRfc1766Info)
2375 return E_INVALIDARG;
2377 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2378 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2379 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2381 if (!SUBLANGID(Locale))
2382 type = LOCALE_SENGLANGUAGE; /* suppress country */
2384 else
2386 if (!SUBLANGID(Locale)) {
2387 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2388 return E_FAIL;
2392 pRfc1766Info->lcid = Locale;
2393 pRfc1766Info->wszRfc1766[0] = 0;
2394 pRfc1766Info->wszLocaleName[0] = 0;
2396 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2397 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2398 return S_OK;
2400 /* Locale not supported */
2401 return E_INVALIDARG;
2404 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2405 IMultiLanguage* iface,
2406 UINT src_cp,
2407 UINT dst_cp,
2408 DWORD prop,
2409 IMLangConvertCharset** convert_charset)
2411 MLang_impl *This = impl_from_IMultiLanguage(iface);
2412 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2415 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2417 fnIMultiLanguage_QueryInterface,
2418 fnIMultiLanguage_AddRef,
2419 fnIMultiLanguage_Release,
2420 fnIMultiLanguage_GetNumberOfCodePageInfo,
2421 fnIMultiLanguage_GetCodePageInfo,
2422 fnIMultiLanguage_GetFamilyCodePage,
2423 fnIMultiLanguage_EnumCodePages,
2424 fnIMultiLanguage_GetCharsetInfo,
2425 fnIMultiLanguage_IsConvertible,
2426 fnIMultiLanguage_ConvertString,
2427 fnIMultiLanguage_ConvertStringToUnicode,
2428 fnIMultiLanguage_ConvertStringFromUnicode,
2429 fnIMultiLanguage_ConvertStringReset,
2430 fnIMultiLanguage_GetRfc1766FromLcid,
2431 fnIMultiLanguage_GetLcidFromRfc1766,
2432 fnIMultiLanguage_EnumRfc1766,
2433 fnIMultiLanguage_GetRfc1766Info,
2434 fnIMultiLanguage_CreateConvertCharset,
2438 /******************************************************************************/
2440 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2442 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2445 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2446 IMultiLanguage3* iface,
2447 REFIID riid,
2448 void** obj)
2450 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2452 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2454 if (IsEqualGUID(riid, &IID_IUnknown) ||
2455 IsEqualGUID(riid, &IID_IMultiLanguage))
2457 *obj = &This->IMultiLanguage_iface;
2459 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2460 IsEqualGUID(riid, &IID_IMLangFontLink))
2462 *obj = &This->IMLangFontLink_iface;
2464 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2466 *obj = &This->IMLangFontLink2_iface;
2468 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2469 IsEqualGUID(riid, &IID_IMultiLanguage3))
2471 *obj = &This->IMultiLanguage3_iface;
2473 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2475 *obj = &This->IMLangLineBreakConsole_iface;
2477 else
2479 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2480 *obj = NULL;
2481 return E_NOINTERFACE;
2484 IMultiLanguage3_AddRef(iface);
2485 return S_OK;
2488 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2490 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2491 return InterlockedIncrement(&This->ref);
2494 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2496 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2497 ULONG ref = InterlockedDecrement(&This->ref);
2499 TRACE("(%p)->(%d)\n", This, ref);
2500 if (ref == 0)
2502 HeapFree(GetProcessHeap(), 0, This);
2503 UnlockModule();
2506 return ref;
2509 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2510 IMultiLanguage3* iface,
2511 UINT* pcCodePage)
2513 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2515 TRACE("%p, %p\n", This, pcCodePage);
2517 if (!pcCodePage) return E_INVALIDARG;
2519 *pcCodePage = This->total_cp;
2520 return S_OK;
2523 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2525 CHARSETINFO csi;
2527 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2528 TCI_SRCCODEPAGE))
2529 mime_cp_info->bGDICharset = csi.ciCharset;
2530 else
2531 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2533 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2534 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2535 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2536 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
2537 mime_cp_info->wszDescription, sizeof(mime_cp_info->wszDescription)/sizeof(WCHAR));
2538 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
2539 mime_cp_info->wszWebCharset, sizeof(mime_cp_info->wszWebCharset)/sizeof(WCHAR));
2540 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
2541 mime_cp_info->wszHeaderCharset, sizeof(mime_cp_info->wszHeaderCharset)/sizeof(WCHAR));
2542 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
2543 mime_cp_info->wszBodyCharset, sizeof(mime_cp_info->wszBodyCharset)/sizeof(WCHAR));
2545 MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
2546 mime_cp_info->wszFixedWidthFont, sizeof(mime_cp_info->wszFixedWidthFont)/sizeof(WCHAR));
2547 MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
2548 mime_cp_info->wszProportionalFont, sizeof(mime_cp_info->wszProportionalFont)/sizeof(WCHAR));
2550 TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
2551 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2552 mime_cp_info->uiFamilyCodePage,
2553 wine_dbgstr_w(mime_cp_info->wszDescription),
2554 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2555 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2556 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2557 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2558 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2559 mime_cp_info->bGDICharset);
2562 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2563 IMultiLanguage3* iface,
2564 UINT uiCodePage,
2565 LANGID LangId,
2566 PMIMECPINFO pCodePageInfo)
2568 UINT i, n;
2569 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2571 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2573 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2575 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2577 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2579 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2580 return S_OK;
2585 return S_FALSE;
2588 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2589 IMultiLanguage3* iface,
2590 UINT uiCodePage,
2591 UINT* puiFamilyCodePage)
2593 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2596 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2597 IMultiLanguage3* iface,
2598 DWORD grfFlags,
2599 LANGID LangId,
2600 IEnumCodePage** ppEnumCodePage)
2602 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2604 TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2606 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2609 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2610 IMultiLanguage3* iface,
2611 BSTR Charset,
2612 PMIMECSETINFO pCharsetInfo)
2614 UINT i, n;
2615 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2617 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2619 if (!pCharsetInfo) return E_FAIL;
2621 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2623 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2625 WCHAR csetW[MAX_MIMECSET_NAME];
2627 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
2628 if (!lstrcmpiW(Charset, csetW))
2630 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2631 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2632 strcpyW(pCharsetInfo->wszCharset, csetW);
2633 return S_OK;
2635 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2637 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2638 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2639 strcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2640 return S_OK;
2645 /* FIXME:
2646 * Since we do not support charsets like iso-2022-jp and do not have
2647 * them in our database as a primary (web_charset) encoding this loop
2648 * does an attempt to 'approximate' charset name by header_charset.
2650 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2652 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2654 WCHAR csetW[MAX_MIMECSET_NAME];
2656 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
2657 if (!lstrcmpiW(Charset, csetW))
2659 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2660 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2661 strcpyW(pCharsetInfo->wszCharset, csetW);
2662 return S_OK;
2667 return E_FAIL;
2670 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2671 IMultiLanguage3* iface,
2672 DWORD dwSrcEncoding,
2673 DWORD dwDstEncoding)
2675 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2678 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2679 IMultiLanguage3* iface,
2680 DWORD* pdwMode,
2681 DWORD dwSrcEncoding,
2682 DWORD dwDstEncoding,
2683 BYTE* pSrcStr,
2684 UINT* pcSrcSize,
2685 BYTE* pDstStr,
2686 UINT* pcDstSize)
2688 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2689 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2692 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2693 IMultiLanguage3* iface,
2694 DWORD* pdwMode,
2695 DWORD dwEncoding,
2696 CHAR* pSrcStr,
2697 UINT* pcSrcSize,
2698 WCHAR* pDstStr,
2699 UINT* pcDstSize)
2701 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2702 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2705 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2706 IMultiLanguage3* iface,
2707 DWORD* pdwMode,
2708 DWORD dwEncoding,
2709 WCHAR* pSrcStr,
2710 UINT* pcSrcSize,
2711 CHAR* pDstStr,
2712 UINT* pcDstSize)
2714 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2715 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2718 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2719 IMultiLanguage3* iface)
2721 FIXME("\n");
2722 return E_NOTIMPL;
2725 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2726 IMultiLanguage3* iface,
2727 LCID lcid,
2728 BSTR* pbstrRfc1766)
2730 WCHAR buf[MAX_RFC1766_NAME];
2732 TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
2733 if (!pbstrRfc1766)
2734 return E_INVALIDARG;
2736 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2738 *pbstrRfc1766 = SysAllocString( buf );
2739 return S_OK;
2741 return E_FAIL;
2744 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2745 IMultiLanguage3* iface,
2746 LCID* pLocale,
2747 BSTR bstrRfc1766)
2749 HRESULT hr;
2750 IEnumRfc1766 *rfc1766;
2752 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2754 if (!pLocale || !bstrRfc1766)
2755 return E_INVALIDARG;
2757 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2758 if (FAILED(hr))
2759 return hr;
2761 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2763 IEnumRfc1766_Release(rfc1766);
2764 return hr;
2767 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2768 IMultiLanguage3* iface,
2769 LANGID LangId,
2770 IEnumRfc1766** ppEnumRfc1766)
2772 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2774 TRACE("%p %p\n", This, ppEnumRfc1766);
2776 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2779 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2780 IMultiLanguage3* iface,
2781 LCID Locale,
2782 LANGID LangId,
2783 PRFC1766INFO pRfc1766Info)
2785 static LANGID last_lang = -1;
2786 LCTYPE type = LOCALE_SLANGUAGE;
2788 TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2790 if (!pRfc1766Info)
2791 return E_INVALIDARG;
2793 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2794 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2795 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2797 if (!SUBLANGID(Locale))
2798 type = LOCALE_SENGLANGUAGE; /* suppress country */
2800 else
2802 if (!SUBLANGID(Locale)) {
2803 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2804 return E_FAIL;
2808 pRfc1766Info->lcid = Locale;
2809 pRfc1766Info->wszRfc1766[0] = 0;
2810 pRfc1766Info->wszLocaleName[0] = 0;
2812 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2813 (last_lang != LangId)) {
2814 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2815 last_lang = LangId;
2818 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2819 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2820 return S_OK;
2822 /* Locale not supported */
2823 return E_INVALIDARG;
2826 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2827 IMultiLanguage3* iface,
2828 UINT src_cp,
2829 UINT dst_cp,
2830 DWORD prop,
2831 IMLangConvertCharset** convert_charset)
2833 HRESULT hr;
2835 TRACE("(%u %u 0x%08x %p)\n", src_cp, dst_cp, prop, convert_charset);
2837 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2838 if (FAILED(hr)) return hr;
2840 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2843 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2844 IMultiLanguage3* iface,
2845 DWORD* pdwMode,
2846 DWORD dwFlag,
2847 WCHAR* lpFallBack,
2848 DWORD dwSrcEncoding,
2849 DWORD dwDstEncoding,
2850 IStream* pstmIn,
2851 IStream* pstmOut)
2853 char *src, *dst = NULL;
2854 INT srclen, dstlen;
2855 STATSTG stat;
2856 HRESULT hr;
2858 TRACE("%p %0x8 %s %u %u %p %p\n",
2859 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2861 FIXME("dwFlag and lpFallBack not handled\n");
2863 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2864 if (FAILED(hr)) return hr;
2866 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
2867 if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
2869 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
2870 if (FAILED(hr)) goto exit;
2872 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
2873 if (FAILED(hr)) goto exit;
2875 if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
2877 hr = E_OUTOFMEMORY;
2878 goto exit;
2880 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
2881 if (FAILED(hr)) goto exit;
2883 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
2885 exit:
2886 HeapFree(GetProcessHeap(), 0, src);
2887 HeapFree(GetProcessHeap(), 0, dst);
2888 return hr;
2891 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
2892 IMultiLanguage3* iface,
2893 DWORD* pdwMode,
2894 DWORD dwEncoding,
2895 CHAR* pSrcStr,
2896 UINT* pcSrcSize,
2897 WCHAR* pDstStr,
2898 UINT* pcDstSize,
2899 DWORD dwFlag,
2900 WCHAR* lpFallBack)
2902 if (dwFlag || lpFallBack)
2903 FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
2904 dwFlag, dwFlag, lpFallBack);
2906 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2907 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2910 /*****************************************************************************
2911 * MultiLanguage2::ConvertStringToUnicodeEx
2913 * Translates the multibyte string from the specified code page to Unicode.
2915 * PARAMS
2916 * see ConvertStringToUnicode
2917 * dwFlag
2918 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
2919 * instead unconvertible characters.
2921 * RETURNS
2922 * S_OK Success.
2923 * S_FALSE The conversion is not supported.
2924 * E_FAIL Some error has occurred.
2926 * TODO: handle dwFlag and lpFallBack
2928 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
2929 IMultiLanguage3* This,
2930 DWORD* pdwMode,
2931 DWORD dwEncoding,
2932 WCHAR* pSrcStr,
2933 UINT* pcSrcSize,
2934 CHAR* pDstStr,
2935 UINT* pcDstSize,
2936 DWORD dwFlag,
2937 WCHAR* lpFallBack)
2939 FIXME("\n");
2940 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2941 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2944 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
2945 IMultiLanguage3* iface,
2946 DWORD dwFlag,
2947 DWORD dwPrefWinCodePage,
2948 IStream* pstmIn,
2949 DetectEncodingInfo* lpEncoding,
2950 INT* pnScores)
2952 FIXME("\n");
2953 return E_NOTIMPL;
2956 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
2957 IMultiLanguage3* iface,
2958 DWORD dwFlag,
2959 DWORD dwPrefWinCodePage,
2960 CHAR* pSrcStr,
2961 INT* pcSrcSize,
2962 DetectEncodingInfo* lpEncoding,
2963 INT* pnScores)
2965 FIXME("\n");
2966 return E_NOTIMPL;
2969 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
2970 IMultiLanguage3* iface,
2971 UINT uiCodePage,
2972 HWND hwnd)
2974 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
2977 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
2978 IMultiLanguage3* iface,
2979 UINT uiCodePage,
2980 LCID lcid,
2981 LPWSTR lpWideCharStr,
2982 int cchWideChar)
2984 /* Find first instance */
2985 unsigned int i,n;
2987 TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
2988 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2990 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2992 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2994 MultiByteToWideChar(CP_ACP, 0,
2995 mlang_data[i].mime_cp_info[n].description,
2996 -1, lpWideCharStr, cchWideChar);
2997 return S_OK;
3002 return S_FALSE;
3005 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
3006 IMultiLanguage3* iface,
3007 UINT uiCodePage)
3009 TRACE("%u\n", uiCodePage);
3011 /* FIXME: the installable set is usually larger than the set of valid codepages */
3012 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
3015 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
3016 IMultiLanguage3* iface,
3017 MIMECONTF dwSource)
3019 FIXME("0x%08x\n", dwSource);
3020 return S_OK;
3023 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
3024 IMultiLanguage3* iface,
3025 UINT* pnScripts)
3027 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3029 TRACE("%p %p\n", This, pnScripts);
3031 if (!pnScripts) return S_FALSE;
3033 *pnScripts = This->total_scripts;
3034 return S_OK;
3037 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3038 IMultiLanguage3* iface,
3039 DWORD dwFlags,
3040 LANGID LangId,
3041 IEnumScript** ppEnumScript)
3043 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3045 TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3047 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3050 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3051 IMultiLanguage3* iface,
3052 UINT uiCodePage,
3053 HWND hwnd,
3054 DWORD dwfIODControl)
3056 unsigned int i;
3057 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3059 TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
3061 /* quick check for kernel32 supported code pages */
3062 if (IsValidCodePage(uiCodePage))
3063 return S_OK;
3065 /* check for mlang supported code pages */
3066 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3068 UINT n;
3069 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3071 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3072 return S_OK;
3076 if (dwfIODControl != CPIOD_PEEK)
3077 FIXME("Request to install codepage language pack not handled\n");
3079 return S_FALSE;
3082 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3083 IMultiLanguage3 *iface,
3084 DWORD dwFlags,
3085 LPCWSTR lpWideCharStr,
3086 UINT cchWideChar,
3087 UINT *puiPreferredCodePages,
3088 UINT nPreferredCodePages,
3089 UINT *puiDetectedCodePages,
3090 UINT *pnDetectedCodePages,
3091 WCHAR *lpSpecialChar)
3093 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3095 FIXME("(%p)->(%08x %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3096 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3097 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3098 debugstr_w(lpSpecialChar));
3100 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3101 return E_INVALIDARG;
3103 puiDetectedCodePages[0] = CP_UTF8;
3104 *pnDetectedCodePages = 1;
3105 return S_OK;
3108 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3109 IMultiLanguage3 *iface,
3110 DWORD dwFlags,
3111 IStream *pStrIn,
3112 UINT *puiPreferredCodePages,
3113 UINT nPreferredCodePages,
3114 UINT *puiDetectedCodePages,
3115 UINT *pnDetectedCodePages,
3116 WCHAR *lpSpecialChar)
3118 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3120 FIXME("(%p)->(%08x %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3121 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3122 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3123 debugstr_w(lpSpecialChar));
3125 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3126 return E_INVALIDARG;
3128 puiDetectedCodePages[0] = CP_UTF8;
3129 *pnDetectedCodePages = 1;
3130 return S_OK;
3133 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3135 fnIMultiLanguage3_QueryInterface,
3136 fnIMultiLanguage3_AddRef,
3137 fnIMultiLanguage3_Release,
3138 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3139 fnIMultiLanguage3_GetCodePageInfo,
3140 fnIMultiLanguage3_GetFamilyCodePage,
3141 fnIMultiLanguage3_EnumCodePages,
3142 fnIMultiLanguage3_GetCharsetInfo,
3143 fnIMultiLanguage3_IsConvertible,
3144 fnIMultiLanguage3_ConvertString,
3145 fnIMultiLanguage3_ConvertStringToUnicode,
3146 fnIMultiLanguage3_ConvertStringFromUnicode,
3147 fnIMultiLanguage3_ConvertStringReset,
3148 fnIMultiLanguage3_GetRfc1766FromLcid,
3149 fnIMultiLanguage3_GetLcidFromRfc1766,
3150 fnIMultiLanguage3_EnumRfc1766,
3151 fnIMultiLanguage3_GetRfc1766Info,
3152 fnIMultiLanguage3_CreateConvertCharset,
3153 fnIMultiLanguage3_ConvertStringInIStream,
3154 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3155 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3156 fnIMultiLanguage3_DetectCodepageInIStream,
3157 fnIMultiLanguage3_DetectInputCodepage,
3158 fnIMultiLanguage3_ValidateCodePage,
3159 fnIMultiLanguage3_GetCodePageDescription,
3160 fnIMultiLanguage3_IsCodePageInstallable,
3161 fnIMultiLanguage3_SetMimeDBSource,
3162 fnIMultiLanguage3_GetNumberOfScripts,
3163 fnIMultiLanguage3_EnumScripts,
3164 fnIMultiLanguage3_ValidateCodePageEx,
3165 fnIMultiLanguage3_DetectOutboundCodePage,
3166 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3169 /******************************************************************************/
3171 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3173 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3176 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3177 IMLangFontLink2 * iface,
3178 REFIID riid,
3179 void** ppvObject)
3181 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3182 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3185 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3187 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3188 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3191 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3193 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3194 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3197 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3198 WCHAR ch_src, DWORD *ret_codepages)
3200 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3201 unsigned int i;
3203 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3205 *ret_codepages = 0;
3207 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3209 BOOL used_dc;
3210 CHAR buf;
3212 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3213 &ch_src, 1, &buf, 1, NULL, &used_dc);
3215 /* If default char is not used, current codepage include the given symbol */
3216 if (!used_dc)
3218 DWORD codepages;
3220 IMLangFontLink2_CodePageToCodePages(iface,
3221 mlang_data[i].family_codepage, &codepages);
3222 *ret_codepages |= codepages;
3225 return S_OK;
3228 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3229 const WCHAR *src, LONG src_len, DWORD priority_cp,
3230 DWORD *codepages, LONG *ret_len)
3232 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3233 LONG i;
3234 DWORD cps = 0;
3236 TRACE("(%p)->(%s:%d %x %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3237 codepages, ret_len);
3239 if (codepages) *codepages = 0;
3240 if (ret_len) *ret_len = 0;
3242 if (!src || !src_len || src_len < 0)
3243 return E_INVALIDARG;
3245 for (i = 0; i < src_len; i++)
3247 DWORD cp;
3248 HRESULT ret;
3250 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3251 if (ret != S_OK) return E_FAIL;
3253 if (!cps) cps = cp;
3254 else cps &= cp;
3256 /* FIXME: not tested */
3257 if (priority_cp & cps) break;
3260 if (codepages) *codepages = cps;
3261 if (ret_len) *ret_len = min( i + 1, src_len );
3262 return S_OK;
3265 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3266 UINT codepage,
3267 DWORD *codepages)
3269 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3270 CHARSETINFO cs;
3271 BOOL rc;
3273 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3275 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3276 if (rc)
3278 *codepages = cs.fs.fsCsb[0];
3279 TRACE("resulting codepages 0x%x\n", *codepages);
3280 return S_OK;
3283 TRACE("codepage not found\n");
3284 *codepages = 0;
3285 return E_FAIL;
3288 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3289 DWORD codepages, UINT def_codepage, UINT *codepage)
3291 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3292 DWORD mask = 0;
3293 CHARSETINFO cs;
3294 BOOL rc;
3295 UINT i;
3297 TRACE("(%p)->(0x%x %u %p)\n", This, codepages, def_codepage, codepage);
3299 *codepage = 0;
3301 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3302 if (rc && (codepages & cs.fs.fsCsb[0]))
3304 TRACE("Found Default Codepage\n");
3305 *codepage = def_codepage;
3306 return S_OK;
3309 for (i = 0; i < 32; i++)
3311 mask = 1 << i;
3312 if (codepages & mask)
3314 DWORD Csb[2];
3315 Csb[0] = mask;
3316 Csb[1] = 0x0;
3317 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3318 if (!rc)
3319 continue;
3321 TRACE("Falling back to least significant found CodePage %u\n",
3322 cs.ciACP);
3323 *codepage = cs.ciACP;
3324 return S_OK;
3328 TRACE("no codepage found\n");
3329 return E_FAIL;
3332 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3333 HDC hdc, HFONT hfont, DWORD *codepages)
3335 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3336 FONTSIGNATURE fontsig;
3337 HFONT old_font;
3339 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3341 old_font = SelectObject(hdc, hfont);
3342 GetTextCharsetInfo(hdc, &fontsig, 0);
3343 SelectObject(hdc, old_font);
3345 *codepages = fontsig.fsCsb[0];
3346 TRACE("ret 0x%x\n", fontsig.fsCsb[0]);
3348 return S_OK;
3351 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3352 HFONT hFont)
3354 FIXME("(%p)->%p\n",This, hFont);
3355 return E_NOTIMPL;
3358 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3360 FIXME("(%p)->\n",This);
3361 return E_NOTIMPL;
3364 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3365 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3367 FIXME("(%p)->%p %i %s %p\n",This, hDC, dwCodePages, debugstr_wn(&chSrc,1), pFont);
3368 return E_NOTIMPL;
3371 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3372 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3374 DWORD size;
3375 GLYPHSET *gs;
3377 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3379 if (!puiRanges) return E_INVALIDARG;
3380 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3381 if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3383 GetFontUnicodeRanges(hDC, gs);
3384 *puiRanges = gs->cRanges;
3385 if (pUranges)
3387 UINT i;
3388 for (i = 0; i < gs->cRanges; i++)
3390 if (i >= *puiRanges) break;
3391 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3392 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3394 *puiRanges = i;
3396 HeapFree(GetProcessHeap(), 0, gs);
3397 return S_OK;
3400 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3401 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3402 SCRIPTFONTINFO *pScriptFont)
3404 UINT i, j;
3406 TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3408 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3410 for (i = 0, j = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3412 if (sid == mlang_data[i].sid)
3414 if (pScriptFont)
3416 if (j >= *puiFonts) break;
3418 pScriptFont[j].scripts = 1 << mlang_data[i].sid;
3419 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3421 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
3422 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3424 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3426 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
3427 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3430 j++;
3433 *puiFonts = j;
3434 return S_OK;
3437 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3438 UINT uiCodePage, SCRIPT_ID *pSid)
3440 UINT i;
3442 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3444 if (uiCodePage == CP_UNICODE) return E_FAIL;
3446 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3448 if (uiCodePage == mlang_data[i].family_codepage)
3450 if (pSid) *pSid = mlang_data[i].sid;
3451 return S_OK;
3454 return E_FAIL;
3457 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3459 fnIMLangFontLink2_QueryInterface,
3460 fnIMLangFontLink2_AddRef,
3461 fnIMLangFontLink2_Release,
3462 fnIMLangFontLink2_GetCharCodePages,
3463 fnIMLangFontLink2_GetStrCodePages,
3464 fnIMLangFontLink2_CodePageToCodePages,
3465 fnIMLangFontLink2_CodePagesToCodePage,
3466 fnIMLangFontLink2_GetFontCodePages,
3467 fnIMLangFontLink2_ReleaseFont,
3468 fnIMLangFontLink2_ResetFontMapping,
3469 fnIMLangFontLink2_MapFont,
3470 fnIMLangFontLink2_GetFontUnicodeRanges,
3471 fnIMLangFontLink2_GetScriptFontInfo,
3472 fnIMLangFontLink2_CodePageToScriptID
3475 /******************************************************************************/
3477 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3479 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3482 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3483 IMLangLineBreakConsole* iface,
3484 REFIID riid,
3485 void** ppvObject)
3487 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3488 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3491 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3492 IMLangLineBreakConsole* iface )
3494 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3495 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3498 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3499 IMLangLineBreakConsole* iface )
3501 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3502 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3505 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3506 IMLangLineBreakConsole* iface,
3507 IMLangString* pSrcMLStr,
3508 LONG lSrcPos,
3509 LONG lSrcLen,
3510 LONG cMinColumns,
3511 LONG cMaxColumns,
3512 LONG* plLineLen,
3513 LONG* plSkipLen)
3515 FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3516 return E_NOTIMPL;
3519 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3520 IMLangLineBreakConsole* iface,
3521 LCID locale,
3522 const WCHAR* pszSrc,
3523 LONG cchSrc,
3524 LONG cMaxColumns,
3525 LONG* pcchLine,
3526 LONG* pcchSkip )
3528 FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3530 *pcchLine = cchSrc;
3531 *pcchSkip = 0;
3532 return S_OK;
3535 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3536 IMLangLineBreakConsole* iface,
3537 LCID locale,
3538 UINT uCodePage,
3539 const CHAR* pszSrc,
3540 LONG cchSrc,
3541 LONG cMaxColumns,
3542 LONG* pcchLine,
3543 LONG* pcchSkip)
3545 LONG i, line = cchSrc, skip = 0;
3547 FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3549 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3551 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3553 if (pszSrc[i] == ' ')
3555 while (i >= 0 && pszSrc[i] == ' ')
3557 i--;
3558 line--;
3559 skip++;
3561 break;
3565 *pcchLine = line;
3566 *pcchSkip = skip;
3567 return S_OK;
3570 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3572 fnIMLangLineBreakConsole_QueryInterface,
3573 fnIMLangLineBreakConsole_AddRef,
3574 fnIMLangLineBreakConsole_Release,
3575 fnIMLangLineBreakConsole_BreakLineML,
3576 fnIMLangLineBreakConsole_BreakLineW,
3577 fnIMLangLineBreakConsole_BreakLineA
3580 struct convert_charset {
3581 IMLangConvertCharset IMLangConvertCharset_iface;
3582 LONG ref;
3584 UINT src_cp;
3585 UINT dst_cp;
3588 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3590 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3593 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3595 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3597 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3599 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3601 *obj = &This->IMLangConvertCharset_iface;
3602 IMLangConvertCharset_AddRef(iface);
3603 return S_OK;
3606 *obj = NULL;
3607 return E_NOINTERFACE;
3610 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3612 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3613 ULONG ref = InterlockedIncrement(&This->ref);
3614 TRACE("(%p)->(%u)\n", This, ref);
3615 return ref;
3618 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3620 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3621 ULONG ref = InterlockedDecrement(&This->ref);
3623 TRACE("(%p)->(%u)\n", This, ref);
3624 if (!ref)
3626 HeapFree(GetProcessHeap(), 0, This);
3627 UnlockModule();
3630 return ref;
3633 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3634 UINT src_cp, UINT dst_cp, DWORD prop)
3636 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3638 TRACE("(%p)->(%u %u 0x%08x)\n", This, src_cp, dst_cp, prop);
3640 prop &= ~MLCONVCHARF_USEDEFCHAR;
3641 if (prop)
3642 FIXME("property 0x%08x not supported\n", prop);
3644 This->src_cp = src_cp;
3645 This->dst_cp = dst_cp;
3647 return S_OK;
3650 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3652 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3654 TRACE("(%p)->(%p)\n", This, src_cp);
3656 if (!src_cp) return E_INVALIDARG;
3657 *src_cp = This->src_cp;
3658 return S_OK;
3661 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3663 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3665 TRACE("(%p)->(%p)\n", This, dst_cp);
3667 if (!dst_cp) return E_INVALIDARG;
3668 *dst_cp = This->dst_cp;
3669 return S_OK;
3672 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3674 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3675 FIXME("(%p)->(%p): stub\n", This, prop);
3676 return E_NOTIMPL;
3679 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3680 UINT *src_size, BYTE *dest, UINT *dest_size)
3682 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3683 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3684 return E_NOTIMPL;
3687 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3688 UINT *src_size, WCHAR *dest, UINT *dest_size)
3690 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3691 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3692 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3695 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3696 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3698 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3699 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3700 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3703 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3705 MLangConvertCharset_QueryInterface,
3706 MLangConvertCharset_AddRef,
3707 MLangConvertCharset_Release,
3708 MLangConvertCharset_Initialize,
3709 MLangConvertCharset_GetSourceCodePage,
3710 MLangConvertCharset_GetDestinationCodePage,
3711 MLangConvertCharset_GetProperty,
3712 MLangConvertCharset_DoConversion,
3713 MLangConvertCharset_DoConversionToUnicode,
3714 MLangConvertCharset_DoConversionFromUnicode
3717 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3719 MLang_impl *mlang;
3720 UINT i;
3722 TRACE("Creating MultiLanguage object\n");
3724 if( pUnkOuter )
3725 return CLASS_E_NOAGGREGATION;
3727 mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3728 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3729 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3730 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3731 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3732 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3734 mlang->total_cp = 0;
3735 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3736 mlang->total_cp += mlang_data[i].number_of_cp;
3738 /* do not enumerate unicode flavours */
3739 mlang->total_scripts = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
3741 mlang->ref = 1;
3742 *ppObj = &mlang->IMultiLanguage_iface;
3743 TRACE("returning %p\n", mlang);
3745 LockModule();
3747 return S_OK;
3750 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3752 struct convert_charset *convert;
3754 if (outer)
3755 return CLASS_E_NOAGGREGATION;
3757 *obj = NULL;
3759 convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3760 if (!convert) return E_OUTOFMEMORY;
3762 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3763 convert->ref = 1;
3765 *obj = &convert->IMLangConvertCharset_iface;
3767 LockModule();
3769 return S_OK;
3772 /******************************************************************************/
3774 HRESULT WINAPI DllCanUnloadNow(void)
3776 return dll_count == 0 ? S_OK : S_FALSE;
3780 /***********************************************************************
3781 * DllRegisterServer (MLANG.@)
3783 HRESULT WINAPI DllRegisterServer(void)
3785 return __wine_register_resources( instance );
3788 /***********************************************************************
3789 * DllUnregisterServer (MLANG.@)
3791 HRESULT WINAPI DllUnregisterServer(void)
3793 return __wine_unregister_resources( instance );
3796 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
3798 if (!unknown) return E_INVALIDARG;
3800 FIXME("%p: stub\n", unknown);
3802 return S_FALSE;