mlang: Add a stub implementation of IMultiLanguage3::DetectOutboundCodePageInIStream.
[wine.git] / dlls / mlang / mlang.c
blobf6bd308677c489034fcc29006f4b2c9b0c9fb3aa
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 (GB2312)",
122 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
123 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
124 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
125 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
126 "gb2312", "gb2312", "gb2312" },
127 { "Chinese Simplified (GBK)",
128 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
129 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
130 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
131 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
132 "gbk", "gbk", "gbk" }
134 static const MIME_CP_INFO chinese_traditional_cp[] =
136 { "Chinese Traditional (Big5)",
137 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
138 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
139 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
140 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
141 "big5", "big5", "big5" }
143 static const MIME_CP_INFO central_european_cp[] =
145 { "Central European (DOS)",
146 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
147 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
148 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
149 "ibm852", "ibm852", "ibm852" },
150 { "Central European (Windows)",
151 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
152 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
153 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
154 MIMECONTF_MIME_LATEST,
155 "windows-1250", "windows-1250", "windows-1250" },
156 { "Central European (Mac)",
157 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
158 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
159 "x-mac-ce", "x-mac-ce", "x-mac-ce" },
160 { "Central European (ISO)",
161 28592, 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 "iso-8859-2", "iso-8859-2", "iso-8859-2" }
167 static const MIME_CP_INFO cyrillic_cp[] =
169 { "OEM Cyrillic",
170 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
171 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
172 "ibm855", "ibm855", "ibm855" },
173 { "Cyrillic (DOS)",
174 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
175 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
176 MIMECONTF_MIME_LATEST,
177 "cp866", "cp866", "cp866" },
178 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
179 { "Cyrillic (KOI8-R)",
180 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
181 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
182 "koi8-r", "koi8-r", "koi8-r" },
183 #endif
184 { "Cyrillic (Windows)",
185 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
186 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
187 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
188 "windows-1251", "windows-1251", "windows-1251" },
189 { "Cyrillic (Mac)",
190 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
191 MIMECONTF_MIME_LATEST,
192 "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
193 { "Cyrillic (KOI8-R)",
194 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
195 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
196 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
197 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
198 "koi8-r", "koi8-r", "koi8-r" },
199 { "Cyrillic (KOI8-U)",
200 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
201 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
202 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
203 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
204 "koi8-u", "koi8-u", "koi8-u" },
205 { "Cyrillic (ISO)",
206 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
207 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
208 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
209 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
210 "iso-8859-5", "iso-8859-5", "iso-8859-5" }
212 static const MIME_CP_INFO greek_cp[] =
214 { "Greek (DOS)",
215 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
216 MIMECONTF_MIME_LATEST,
217 "ibm737", "ibm737", "ibm737" },
218 { "Greek, Modern (DOS)",
219 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
220 MIMECONTF_MIME_LATEST,
221 "ibm869", "ibm869", "ibm869" },
222 { "IBM EBCDIC (Greek Modern)",
223 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
224 MIMECONTF_MIME_LATEST,
225 "cp875", "cp875", "cp875" },
226 { "Greek (Windows)",
227 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
228 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
229 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
230 "windows-1253", "windows-1253", "windows-1253" },
231 { "Greek (Mac)",
232 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
233 MIMECONTF_MIME_LATEST,
234 "x-mac-greek", "x-mac-greek", "x-mac-greek" },
235 { "Greek (ISO)",
236 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
237 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
238 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
239 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
240 "iso-8859-7", "iso-8859-7", "iso-8859-7" }
242 static const MIME_CP_INFO hebrew_cp[] =
244 { "Hebrew (424)",
245 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
246 MIMECONTF_MIME_LATEST,
247 "ibm424", "ibm424", "ibm424" },
248 { "Hebrew (856)",
249 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
250 MIMECONTF_MIME_LATEST,
251 "cp856", "cp856", "cp856" },
252 { "Hebrew (DOS)",
253 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
254 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
255 MIMECONTF_MIME_LATEST,
256 "dos-862", "dos-862", "dos-862" },
257 { "Hebrew (Windows)",
258 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
259 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
260 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
261 "windows-1255", "windows-1255", "windows-1255" },
262 { "Hebrew (ISO-Visual)",
263 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
264 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
265 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
266 "iso-8859-8", "iso-8859-8", "iso-8859-8" }
268 static const MIME_CP_INFO japanese_cp[] =
270 { "Japanese (Auto-Select)",
271 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
272 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
273 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
274 "_autodetect", "_autodetect", "_autodetect" },
275 { "Japanese (EUC)",
276 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
277 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
278 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
279 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
280 "euc-jp", "euc-jp", "euc-jp" },
281 { "Japanese (JIS)",
282 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
283 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
284 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
285 MIMECONTF_MIME_IE4,
286 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
287 { "Japanese (JIS 0208-1990 and 0212-1990)",
288 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
289 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
290 "EUC-JP","EUC-JP","EUC-JP"},
291 { "Japanese (JIS-Allow 1 byte Kana)",
292 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
293 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
294 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
295 "csISO2022JP","iso-2022-jp","iso-2022-jp"},
296 { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
297 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
298 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
299 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
300 { "Japanese (Mac)",
301 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
302 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
303 "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
304 { "Japanese (Shift-JIS)",
305 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
306 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
307 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
308 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
309 "shift_jis", "iso-2022-jp", "iso-2022-jp" }
311 static const MIME_CP_INFO korean_cp[] =
313 { "Korean",
314 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
315 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
316 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
317 MIMECONTF_MIME_LATEST,
318 "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
320 static const MIME_CP_INFO thai_cp[] =
322 { "Thai (Windows)",
323 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
324 "ibm-thai", "ibm-thai", "ibm-thai" }
326 static const MIME_CP_INFO turkish_cp[] =
328 { "Turkish (DOS)",
329 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
330 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
331 "ibm857", "ibm857", "ibm857" },
332 { "IBM EBCDIC (Turkish Latin-5)",
333 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
334 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
335 "ibm1026", "ibm1026", "ibm1026" },
336 { "Turkish (Windows)",
337 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
338 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
339 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
340 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
341 "windows-1254", "windows-1254", "windows-1254" },
342 { "Turkish (Mac)",
343 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
344 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
345 "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
346 { "Latin 3 (ISO)",
347 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
348 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
349 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
350 "iso-8859-3", "iso-8859-3", "iso-8859-3" },
351 { "Turkish (ISO)",
352 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
353 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
354 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
355 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
356 "iso-8859-9", "iso-8859-9", "iso-8859-9" }
358 static const MIME_CP_INFO vietnamese_cp[] =
360 { "Vietnamese (Windows)",
361 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
362 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
363 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
364 MIMECONTF_MIME_LATEST,
365 "windows-1258", "windows-1258", "windows-1258" }
368 static const WCHAR asciiW[] = {'a','s','c','i','i',0};
370 static const MIME_CP_INFO western_cp[] =
372 { "IBM EBCDIC (US-Canada)",
373 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
374 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
375 "ibm037", "ibm037", "ibm037" },
376 { "OEM United States",
377 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
378 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
379 "ibm437", "ibm437", "ibm437" },
380 { "IBM EBCDIC (International)",
381 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
382 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
383 "ibm500", "ibm500", "ibm500" },
384 { "Western European (DOS)",
385 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
386 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
387 "ibm850", "ibm850", "ibm850" },
388 { "Portuguese (DOS)",
389 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
390 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
391 "ibm860", "ibm860", "ibm860" },
392 { "Icelandic (DOS)",
393 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
394 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
395 "ibm861", "ibm861", "ibm861" },
396 { "French Canadian (DOS)",
397 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
398 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
399 "ibm863", "ibm863", "ibm863" },
400 { "Nordic (DOS)",
401 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
402 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
403 "ibm865", "ibm865", "ibm865" },
404 { "Western European (Windows)",
405 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
406 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
407 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
408 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
409 "windows-1252", "windows-1252", "iso-8859-1" },
410 { "Western European (Mac)",
411 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
412 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
413 "macintosh", "macintosh", "macintosh" },
414 { "Icelandic (Mac)",
415 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
416 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
417 "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
418 { "US-ASCII",
419 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
420 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
421 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
422 "us-ascii", "us-ascii", "us-ascii", asciiW },
423 { "Western European (ISO)",
424 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
425 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
426 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
427 MIMECONTF_MIME_LATEST,
428 "iso-8859-1", "iso-8859-1", "iso-8859-1" },
429 { "Latin 9 (ISO)",
430 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
431 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
432 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
433 MIMECONTF_MIME_LATEST,
434 "iso-8859-15", "iso-8859-15", "iso-8859-15" }
436 static const MIME_CP_INFO unicode_cp[] =
438 { "Unicode",
439 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
440 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
441 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
442 MIMECONTF_MIME_LATEST,
443 "unicode", "unicode", "unicode" },
444 { "Unicode (UTF-7)",
445 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
446 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
447 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
448 "utf-7", "utf-7", "utf-7" },
449 { "Unicode (UTF-8)",
450 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
451 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
452 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
453 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
454 "utf-8", "utf-8", "utf-8" }
457 static const struct mlang_data
459 const char *description;
460 UINT family_codepage;
461 UINT number_of_cp;
462 const MIME_CP_INFO *mime_cp_info;
463 const char *fixed_font;
464 const char *proportional_font;
465 SCRIPT_ID sid;
466 } mlang_data[] =
468 { "Arabic",1256,sizeof(arabic_cp)/sizeof(arabic_cp[0]),arabic_cp,
469 "Courier","Arial", sidArabic }, /* FIXME */
470 { "Baltic",1257,sizeof(baltic_cp)/sizeof(baltic_cp[0]),baltic_cp,
471 "Courier","Arial", sidAsciiLatin }, /* FIXME */
472 { "Chinese Simplified",936,sizeof(chinese_simplified_cp)/sizeof(chinese_simplified_cp[0]),chinese_simplified_cp,
473 "Courier","Arial", sidHan }, /* FIXME */
474 { "Chinese Traditional",950,sizeof(chinese_traditional_cp)/sizeof(chinese_traditional_cp[0]),chinese_traditional_cp,
475 "Courier","Arial", sidBopomofo }, /* FIXME */
476 { "Central European",1250,sizeof(central_european_cp)/sizeof(central_european_cp[0]),central_european_cp,
477 "Courier","Arial", sidAsciiLatin }, /* FIXME */
478 { "Cyrillic",1251,sizeof(cyrillic_cp)/sizeof(cyrillic_cp[0]),cyrillic_cp,
479 "Courier","Arial", sidCyrillic }, /* FIXME */
480 { "Greek",1253,sizeof(greek_cp)/sizeof(greek_cp[0]),greek_cp,
481 "Courier","Arial", sidGreek }, /* FIXME */
482 { "Hebrew",1255,sizeof(hebrew_cp)/sizeof(hebrew_cp[0]),hebrew_cp,
483 "Courier","Arial", sidHebrew }, /* FIXME */
484 { "Japanese",932,sizeof(japanese_cp)/sizeof(japanese_cp[0]),japanese_cp,
485 "MS Gothic","MS PGothic", sidKana },
486 { "Korean",949,sizeof(korean_cp)/sizeof(korean_cp[0]),korean_cp,
487 "Courier","Arial", sidHangul }, /* FIXME */
488 { "Thai",874,sizeof(thai_cp)/sizeof(thai_cp[0]),thai_cp,
489 "Courier","Arial", sidThai }, /* FIXME */
490 { "Turkish",1254,sizeof(turkish_cp)/sizeof(turkish_cp[0]),turkish_cp,
491 "Courier","Arial", sidAsciiLatin }, /* FIXME */
492 { "Vietnamese",1258,sizeof(vietnamese_cp)/sizeof(vietnamese_cp[0]),vietnamese_cp,
493 "Courier","Arial", sidAsciiLatin }, /* FIXME */
494 { "Western European",1252,sizeof(western_cp)/sizeof(western_cp[0]),western_cp,
495 "Courier","Arial", sidAsciiLatin }, /* FIXME */
496 { "Unicode",CP_UNICODE,sizeof(unicode_cp)/sizeof(unicode_cp[0]),unicode_cp,
497 "Courier","Arial" } /* FIXME */
500 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
502 static LONG dll_count;
505 * Japanese Detection and Converstion Functions
508 #define HANKATA(A) ((A >= 161) && (A <= 223))
509 #define ISEUC(A) ((A >= 161) && (A <= 254))
510 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
511 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
512 #define SJIS2(A) ((A >= 64) && (A <= 252))
513 #define ISMARU(A) ((A >= 202) && (A <= 206))
514 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
516 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
518 UINT code = 0;
519 DWORD i = 0;
520 unsigned char c1,c2;
522 while ((code == 0 || code == 51932) && i < count)
524 c1 = input[i];
525 if (c1 == 0x1b /* ESC */)
527 i++;
528 if (i >= count)
529 return code;
530 c1 = input[i];
531 if (c1 == '$')
533 i++;
534 if (i >= count)
535 return code;
536 c1 = input[i];
537 if (c1 =='B' || c1 == '@')
538 code = 50220;
540 if (c1 == 'K')
541 code = 50220;
543 else if (c1 >= 129)
545 i++;
546 if (i >= count)
547 return code;
548 c2 = input[i];
549 if NOTEUC(c1,c2)
550 code = 932;
551 else if (ISEUC(c1) && ISEUC(c2))
552 code = 51932;
553 else if (((c1 == 142)) && HANKATA(c2))
554 code = 51932;
556 i++;
558 return code;
561 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
563 unsigned char c1 = *p1;
564 unsigned char c2 = *p2;
565 int row = c1 < 95 ? 112 : 176;
566 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
568 *p1 = ((c1 + 1) >> 1) + row;
569 *p2 = c2 + cell;
572 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
574 unsigned char c1 = *p1;
575 unsigned char c2 = *p2;
576 int shift = c2 < 159;
577 int row = c1 < 160 ? 112 : 176;
578 int cell = shift ? (31 + (c2 > 127)): 126;
580 *p1 = ((c1 - row) << 1) - shift;
581 *p2 -= cell;
584 static int han2zen(unsigned char *p1, unsigned char *p2)
586 BOOL maru = FALSE;
587 BOOL nigori = FALSE;
588 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
589 131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
590 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
591 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
592 131,129,129 };
593 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
594 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
595 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
596 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
598 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
599 nigori = TRUE;
600 else if ((*p2 == 223) && (ISMARU(*p1)))
601 maru = TRUE;
603 if (*p1 >= 161 && *p1 <= 223)
605 unsigned char index = *p1 - 161;
606 *p1 = char1[index];
607 *p2 = char2[index];
610 if (maru || nigori)
612 if (nigori)
614 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
615 (*p2)++;
616 else if ((*p1 == 131) && (*p2 == 69))
617 *p2 = 148;
619 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
620 *p2+= 2;
622 return 1;
625 return 0;
629 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
631 DWORD i = 0;
632 int j = 0;
633 unsigned char p2,p;
634 BOOL shifted = FALSE;
636 while (i < count)
638 p = input[i];
639 if (p == 0x1b /* ESC */)
641 i++;
642 if (i >= count)
643 return 0;
644 p2 = input[i];
645 if (p2 == '$' || p2 =='(')
646 i++;
647 if (p2 == 'K' || p2 =='$')
648 shifted = TRUE;
649 else
650 shifted = FALSE;
652 else
654 if (shifted)
656 i++;
657 if (i >= count)
658 return 0;
659 p2 = input[i];
660 jis2sjis(&p,&p2);
661 output[j++]=p;
662 output[j++]=p2;
664 else
666 output[j++] = p;
669 i++;
671 return j;
674 static inline int exit_shift(LPSTR out, int c)
676 if (out)
678 out[c] = 0x1b;
679 out[c+1] = '(';
680 out[c+2] = 'B';
682 return 3;
685 static inline int enter_shift(LPSTR out, int c)
687 if (out)
689 out[c] = 0x1b;
690 out[c+1] = '$';
691 out[c+2] = 'B';
693 return 3;
697 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
699 DWORD i = 0;
700 int j = 0;
701 unsigned char p2,p;
702 BOOL shifted = FALSE;
704 while (i < count)
706 p = input[i] & 0xff;
707 if (p == 10 || p == 13) /* NL and CR */
709 if (shifted)
711 shifted = FALSE;
712 j += exit_shift(output,j);
714 if (output)
715 output[j++] = p;
716 else
717 j++;
719 else
721 if (SJIS1(p))
723 i++;
724 if (i >= count)
725 return 0;
726 p2 = input[i] & 0xff;
727 if (SJIS2(p2))
729 sjis2jis(&p,&p2);
730 if (!shifted)
732 shifted = TRUE;
733 j+=enter_shift(output,j);
737 if (output)
739 output[j++]=p;
740 output[j++]=p2;
742 else
743 j+=2;
745 else
747 if (HANKATA(p))
749 if ((i+1) >= count)
750 return 0;
751 p2 = input[i+1] & 0xff;
752 i+=han2zen(&p,&p2);
753 sjis2jis(&p,&p2);
754 if (!shifted)
756 shifted = TRUE;
757 j+=enter_shift(output,j);
759 if (output)
761 output[j++]=p;
762 output[j++]=p2;
764 else
765 j+=2;
767 else
769 if (shifted)
771 shifted = FALSE;
772 j += exit_shift(output,j);
774 if (output)
775 output[j++]=p;
776 else
777 j++;
781 i++;
783 if (shifted)
784 j += exit_shift(output,j);
785 return j;
788 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
789 LPWSTR output, DWORD out_count)
791 CHAR *sjis_string;
792 UINT rc = 0;
793 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
794 rc = ConvertJIS2SJIS(input,count,sjis_string);
795 if (rc)
797 TRACE("%s\n",debugstr_an(sjis_string,rc));
798 if (output)
799 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
800 else
801 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
803 HeapFree(GetProcessHeap(),0,sjis_string);
804 return rc;
808 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
809 LPWSTR output, DWORD out_count)
811 CHAR *sjis_string;
812 UINT rc = 0;
813 int code = DetectJapaneseCode(input,count);
814 TRACE("Japanese code %i\n",code);
816 switch (code)
818 case 0:
819 if (output)
820 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
821 else
822 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
823 break;
825 case 932:
826 if (output)
827 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
828 else
829 rc = MultiByteToWideChar(932,0,input,count,0,0);
830 break;
832 case 51932:
833 if (output)
834 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
835 else
836 rc = MultiByteToWideChar(20932,0,input,count,0,0);
837 break;
839 case 50220:
840 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
841 rc = ConvertJIS2SJIS(input,count,sjis_string);
842 if (rc)
844 TRACE("%s\n",debugstr_an(sjis_string,rc));
845 if (output)
846 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
847 else
848 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
850 HeapFree(GetProcessHeap(),0,sjis_string);
851 break;
853 return rc;
856 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
857 LPSTR output, DWORD out_count)
859 CHAR *sjis_string;
860 INT len;
861 UINT rc = 0;
863 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
864 sjis_string = HeapAlloc(GetProcessHeap(),0,len);
865 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
866 TRACE("%s\n",debugstr_an(sjis_string,len));
868 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
869 if (out_count >= rc)
871 ConvertSJIS2JIS(sjis_string, len, output);
873 HeapFree(GetProcessHeap(),0,sjis_string);
874 return rc;
879 * Dll lifetime tracking declaration
881 static void LockModule(void)
883 InterlockedIncrement(&dll_count);
886 static void UnlockModule(void)
888 InterlockedDecrement(&dll_count);
891 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
893 switch(fdwReason) {
894 case DLL_PROCESS_ATTACH:
895 instance = hInstDLL;
896 MLANG_tls_index = TlsAlloc();
897 DisableThreadLibraryCalls(hInstDLL);
898 break;
899 case DLL_PROCESS_DETACH:
900 if (lpv) break;
901 TlsFree(MLANG_tls_index);
902 break;
904 return TRUE;
907 HRESULT WINAPI ConvertINetMultiByteToUnicode(
908 LPDWORD pdwMode,
909 DWORD dwEncoding,
910 LPCSTR pSrcStr,
911 LPINT pcSrcSize,
912 LPWSTR pDstStr,
913 LPINT pcDstSize)
915 INT src_len = -1;
917 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
918 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
920 if (!pcDstSize)
921 return E_FAIL;
923 if (!pcSrcSize)
924 pcSrcSize = &src_len;
926 if (!*pcSrcSize)
928 *pcDstSize = 0;
929 return S_OK;
932 /* forwarding euc-jp to EUC-JP */
933 if (dwEncoding == 51932)
934 dwEncoding = 20932;
936 switch (dwEncoding)
938 case CP_UNICODE:
939 if (*pcSrcSize == -1)
940 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
941 *pcDstSize = min(*pcSrcSize, *pcDstSize);
942 *pcSrcSize *= sizeof(WCHAR);
943 if (pDstStr)
944 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
945 break;
947 case 50220:
948 case 50221:
949 case 50222:
950 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
951 break;
952 case 50932:
953 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
954 break;
956 default:
957 if (*pcSrcSize == -1)
958 *pcSrcSize = lstrlenA(pSrcStr);
960 if (pDstStr)
961 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
962 else
963 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
964 break;
967 if (!*pcDstSize)
968 return E_FAIL;
970 return S_OK;
973 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
974 LPDWORD pdwMode,
975 DWORD dwEncoding,
976 LPCWSTR pSrcStr,
977 LPINT pcSrcSize,
978 LPSTR pDstStr,
979 LPINT pcDstSize)
981 INT destsz, size;
982 INT src_len = -1;
984 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
985 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
987 if (!pcDstSize)
988 return S_OK;
990 if (!pcSrcSize)
991 pcSrcSize = &src_len;
993 destsz = (pDstStr) ? *pcDstSize : 0;
994 *pcDstSize = 0;
996 if (!pSrcStr || !*pcSrcSize)
997 return S_OK;
999 if (*pcSrcSize == -1)
1000 *pcSrcSize = lstrlenW(pSrcStr);
1002 /* forwarding euc-jp to EUC-JP */
1003 if (dwEncoding == 51932)
1004 dwEncoding = 20932;
1006 if (dwEncoding == CP_UNICODE)
1008 if (*pcSrcSize == -1)
1009 *pcSrcSize = lstrlenW(pSrcStr);
1011 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1012 if (pDstStr)
1013 memmove(pDstStr, pSrcStr, size);
1015 if (size >= destsz)
1016 goto fail;
1018 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1020 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1021 if (!size)
1022 goto fail;
1024 if (pDstStr)
1026 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1027 destsz);
1028 if (!size)
1029 goto fail;
1033 else
1035 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1036 NULL, 0, NULL, NULL);
1037 if (!size)
1038 goto fail;
1040 if (pDstStr)
1042 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1043 pDstStr, destsz, NULL, NULL);
1044 if (!size)
1045 goto fail;
1049 *pcDstSize = size;
1050 return S_OK;
1052 fail:
1053 *pcSrcSize = 0;
1054 *pcDstSize = 0;
1055 return E_FAIL;
1058 HRESULT WINAPI ConvertINetString(
1059 LPDWORD pdwMode,
1060 DWORD dwSrcEncoding,
1061 DWORD dwDstEncoding,
1062 LPCSTR pSrcStr,
1063 LPINT pcSrcSize,
1064 LPSTR pDstStr,
1065 LPINT pcDstSize
1068 TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1069 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1071 if (dwSrcEncoding == CP_UNICODE)
1073 INT cSrcSizeW;
1074 if (pcSrcSize && *pcSrcSize != -1)
1076 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1077 pcSrcSize = &cSrcSizeW;
1079 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1081 else if (dwDstEncoding == CP_UNICODE)
1083 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1084 *pcDstSize *= sizeof(WCHAR);
1085 return hr;
1087 else
1089 INT cDstSizeW;
1090 LPWSTR pDstStrW;
1091 HRESULT hr;
1093 TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1095 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1096 if (hr != S_OK)
1097 return hr;
1099 pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1100 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1101 if (hr == S_OK)
1102 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1104 HeapFree(GetProcessHeap(), 0, pDstStrW);
1105 return hr;
1109 static HRESULT GetFamilyCodePage(
1110 UINT uiCodePage,
1111 UINT* puiFamilyCodePage)
1113 UINT i, n;
1115 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1117 if (!puiFamilyCodePage) return S_FALSE;
1119 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1121 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1123 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1125 *puiFamilyCodePage = mlang_data[i].family_codepage;
1126 return S_OK;
1131 return S_FALSE;
1134 HRESULT WINAPI IsConvertINetStringAvailable(
1135 DWORD dwSrcEncoding,
1136 DWORD dwDstEncoding)
1138 UINT src_family, dst_family;
1140 TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
1142 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1143 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1144 return S_FALSE;
1146 if (src_family == dst_family) return S_OK;
1148 /* we can convert any codepage to/from unicode */
1149 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1151 return S_FALSE;
1154 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1156 CHAR buffer[MAX_RFC1766_NAME];
1157 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1158 INT i;
1160 if (n)
1162 i = PRIMARYLANGID(lcid);
1163 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1164 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1165 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1167 buffer[n - 1] = '-';
1168 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1169 if (!i)
1170 buffer[n - 1] = '\0';
1172 else
1173 i = 0;
1175 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1176 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1178 return E_FAIL;
1181 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1183 WCHAR buffer[MAX_RFC1766_NAME];
1184 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1185 INT i;
1187 if (n)
1189 i = PRIMARYLANGID(lcid);
1190 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1191 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1192 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1194 buffer[n - 1] = '-';
1195 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1196 if (!i)
1197 buffer[n - 1] = '\0';
1199 else
1200 i = 0;
1202 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1203 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1205 return E_FAIL;
1208 HRESULT WINAPI LcidToRfc1766A(
1209 LCID lcid,
1210 LPSTR pszRfc1766,
1211 INT nChar)
1213 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1214 if (!pszRfc1766)
1215 return E_INVALIDARG;
1217 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1220 HRESULT WINAPI LcidToRfc1766W(
1221 LCID lcid,
1222 LPWSTR pszRfc1766,
1223 INT nChar)
1225 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1226 if (!pszRfc1766)
1227 return E_INVALIDARG;
1229 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1232 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1234 RFC1766INFO info;
1235 ULONG num;
1237 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1239 if (!strcmpiW(info.wszRfc1766, rfc1766))
1241 *lcid = info.lcid;
1242 return S_OK;
1244 if (strlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1246 *lcid = PRIMARYLANGID(info.lcid);
1247 return S_OK;
1251 return E_FAIL;
1254 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1256 IEnumRfc1766 *enumrfc1766;
1257 HRESULT hr;
1259 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1261 if (!pLocale || !pszRfc1766)
1262 return E_INVALIDARG;
1264 hr = EnumRfc1766_create(0, &enumrfc1766);
1265 if (FAILED(hr))
1266 return hr;
1268 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1269 IEnumRfc1766_Release(enumrfc1766);
1271 return hr;
1274 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1276 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1278 if (!rfc1766A)
1279 return E_INVALIDARG;
1281 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1282 rfc1766W[MAX_RFC1766_NAME] = 0;
1284 return Rfc1766ToLcidW(lcid, rfc1766W);
1287 /******************************************************************************
1288 * MLANG ClassFactory
1290 typedef struct {
1291 IClassFactory IClassFactory_iface;
1292 LONG ref;
1293 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1294 } IClassFactoryImpl;
1296 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1298 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1301 struct object_creation_info
1303 const CLSID *clsid;
1304 LPCSTR szClassName;
1305 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1308 static const struct object_creation_info object_creation[] =
1310 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1311 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1314 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1316 TRACE("%s\n", debugstr_guid(riid) );
1318 if (IsEqualGUID(riid, &IID_IUnknown)
1319 || IsEqualGUID(riid, &IID_IClassFactory))
1321 IClassFactory_AddRef(iface);
1322 *ppobj = iface;
1323 return S_OK;
1326 *ppobj = NULL;
1327 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1328 return E_NOINTERFACE;
1331 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1333 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1334 return InterlockedIncrement(&This->ref);
1337 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1339 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1340 ULONG ref = InterlockedDecrement(&This->ref);
1342 if (ref == 0)
1344 TRACE("Destroying %p\n", This);
1345 HeapFree(GetProcessHeap(), 0, This);
1348 return ref;
1351 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1352 REFIID riid, void **ppobj)
1354 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1355 HRESULT hres;
1356 LPUNKNOWN punk;
1358 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1360 *ppobj = NULL;
1361 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1362 if (SUCCEEDED(hres)) {
1363 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1364 IUnknown_Release(punk);
1366 TRACE("returning (%p) -> %x\n", *ppobj, hres);
1367 return hres;
1370 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1372 if (dolock)
1373 LockModule();
1374 else
1375 UnlockModule();
1377 return S_OK;
1380 static const IClassFactoryVtbl MLANGCF_Vtbl =
1382 MLANGCF_QueryInterface,
1383 MLANGCF_AddRef,
1384 MLANGCF_Release,
1385 MLANGCF_CreateInstance,
1386 MLANGCF_LockServer
1389 /******************************************************************
1390 * DllGetClassObject (MLANG.@)
1392 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1394 unsigned int i;
1395 IClassFactoryImpl *factory;
1397 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1399 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1400 && ! IsEqualGUID( &IID_IUnknown, iid) )
1401 return E_NOINTERFACE;
1403 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
1405 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1406 break;
1409 if (i == sizeof(object_creation)/sizeof(object_creation[0]))
1411 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1412 return CLASS_E_CLASSNOTAVAILABLE;
1415 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1417 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1418 if (factory == NULL) return E_OUTOFMEMORY;
1420 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1421 factory->ref = 1;
1423 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1425 *ppv = &factory->IClassFactory_iface;
1427 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1429 return S_OK;
1433 /******************************************************************************/
1435 typedef struct tagMLang_impl
1437 IMLangFontLink IMLangFontLink_iface;
1438 IMultiLanguage IMultiLanguage_iface;
1439 IMultiLanguage3 IMultiLanguage3_iface;
1440 IMLangFontLink2 IMLangFontLink2_iface;
1441 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1442 LONG ref;
1443 DWORD total_cp, total_scripts;
1444 } MLang_impl;
1446 /******************************************************************************/
1448 typedef struct tagEnumCodePage_impl
1450 IEnumCodePage IEnumCodePage_iface;
1451 LONG ref;
1452 MIMECPINFO *cpinfo;
1453 DWORD total, pos;
1454 } EnumCodePage_impl;
1456 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1458 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1461 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1462 IEnumCodePage* iface,
1463 REFIID riid,
1464 void** ppvObject)
1466 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1468 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1470 if (IsEqualGUID(riid, &IID_IUnknown)
1471 || IsEqualGUID(riid, &IID_IEnumCodePage))
1473 IEnumCodePage_AddRef(iface);
1474 TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
1475 *ppvObject = &This->IEnumCodePage_iface;
1476 return S_OK;
1479 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1480 return E_NOINTERFACE;
1483 static ULONG WINAPI fnIEnumCodePage_AddRef(
1484 IEnumCodePage* iface)
1486 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1487 return InterlockedIncrement(&This->ref);
1490 static ULONG WINAPI fnIEnumCodePage_Release(
1491 IEnumCodePage* iface)
1493 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1494 ULONG ref = InterlockedDecrement(&This->ref);
1496 TRACE("%p ref = %d\n", This, ref);
1497 if (ref == 0)
1499 TRACE("Destroying %p\n", This);
1500 HeapFree(GetProcessHeap(), 0, This->cpinfo);
1501 HeapFree(GetProcessHeap(), 0, This);
1504 return ref;
1507 static HRESULT WINAPI fnIEnumCodePage_Clone(
1508 IEnumCodePage* iface,
1509 IEnumCodePage** ppEnum)
1511 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1512 FIXME("%p %p\n", This, ppEnum);
1513 return E_NOTIMPL;
1516 static HRESULT WINAPI fnIEnumCodePage_Next(
1517 IEnumCodePage* iface,
1518 ULONG celt,
1519 PMIMECPINFO rgelt,
1520 ULONG* pceltFetched)
1522 ULONG i;
1523 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1525 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1527 if (!pceltFetched) return S_FALSE;
1528 *pceltFetched = 0;
1530 if (!rgelt) return S_FALSE;
1532 if (This->pos + celt > This->total)
1533 celt = This->total - This->pos;
1535 if (!celt) return S_FALSE;
1537 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1538 *pceltFetched = celt;
1539 This->pos += celt;
1541 for (i = 0; i < celt; i++)
1543 TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
1544 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1545 rgelt[i].uiFamilyCodePage,
1546 wine_dbgstr_w(rgelt[i].wszDescription),
1547 wine_dbgstr_w(rgelt[i].wszWebCharset),
1548 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1549 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1550 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1551 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1552 rgelt[i].bGDICharset);
1554 return S_OK;
1557 static HRESULT WINAPI fnIEnumCodePage_Reset(
1558 IEnumCodePage* iface)
1560 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1562 TRACE("%p\n", This);
1564 This->pos = 0;
1565 return S_OK;
1568 static HRESULT WINAPI fnIEnumCodePage_Skip(
1569 IEnumCodePage* iface,
1570 ULONG celt)
1572 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1574 TRACE("%p %u\n", This, celt);
1576 if (celt >= This->total) return S_FALSE;
1578 This->pos += celt;
1579 return S_OK;
1582 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1584 fnIEnumCodePage_QueryInterface,
1585 fnIEnumCodePage_AddRef,
1586 fnIEnumCodePage_Release,
1587 fnIEnumCodePage_Clone,
1588 fnIEnumCodePage_Next,
1589 fnIEnumCodePage_Reset,
1590 fnIEnumCodePage_Skip
1593 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1594 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1596 EnumCodePage_impl *ecp;
1597 MIMECPINFO *cpinfo;
1598 UINT i, n;
1600 TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1602 if (!grfFlags) /* enumerate internal data base of encodings */
1603 grfFlags = MIMECONTF_MIME_LATEST;
1605 ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1606 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1607 ecp->ref = 1;
1608 ecp->pos = 0;
1609 ecp->total = 0;
1610 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1612 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1614 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1615 ecp->total++;
1619 ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1620 sizeof(MIMECPINFO) * ecp->total);
1621 cpinfo = ecp->cpinfo;
1623 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1625 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1627 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1628 fill_cp_info(&mlang_data[i], n, cpinfo++);
1632 TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
1634 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1636 return S_OK;
1639 /******************************************************************************/
1641 typedef struct tagEnumScript_impl
1643 IEnumScript IEnumScript_iface;
1644 LONG ref;
1645 SCRIPTINFO *script_info;
1646 DWORD total, pos;
1647 } EnumScript_impl;
1649 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1651 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1654 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1655 IEnumScript* iface,
1656 REFIID riid,
1657 void** ppvObject)
1659 EnumScript_impl *This = impl_from_IEnumScript( iface );
1661 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1663 if (IsEqualGUID(riid, &IID_IUnknown)
1664 || IsEqualGUID(riid, &IID_IEnumScript))
1666 IEnumScript_AddRef(iface);
1667 TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
1668 *ppvObject = &This->IEnumScript_iface;
1669 return S_OK;
1672 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1673 return E_NOINTERFACE;
1676 static ULONG WINAPI fnIEnumScript_AddRef(
1677 IEnumScript* iface)
1679 EnumScript_impl *This = impl_from_IEnumScript( iface );
1680 return InterlockedIncrement(&This->ref);
1683 static ULONG WINAPI fnIEnumScript_Release(
1684 IEnumScript* iface)
1686 EnumScript_impl *This = impl_from_IEnumScript( iface );
1687 ULONG ref = InterlockedDecrement(&This->ref);
1689 TRACE("%p ref = %d\n", This, ref);
1690 if (ref == 0)
1692 TRACE("Destroying %p\n", This);
1693 HeapFree(GetProcessHeap(), 0, This->script_info);
1694 HeapFree(GetProcessHeap(), 0, This);
1697 return ref;
1700 static HRESULT WINAPI fnIEnumScript_Clone(
1701 IEnumScript* iface,
1702 IEnumScript** ppEnum)
1704 EnumScript_impl *This = impl_from_IEnumScript( iface );
1705 FIXME("%p %p: stub!\n", This, ppEnum);
1706 return E_NOTIMPL;
1709 static HRESULT WINAPI fnIEnumScript_Next(
1710 IEnumScript* iface,
1711 ULONG celt,
1712 PSCRIPTINFO rgelt,
1713 ULONG* pceltFetched)
1715 EnumScript_impl *This = impl_from_IEnumScript( iface );
1717 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1719 if (!pceltFetched || !rgelt) return E_FAIL;
1721 *pceltFetched = 0;
1723 if (This->pos + celt > This->total)
1724 celt = This->total - This->pos;
1726 if (!celt) return S_FALSE;
1728 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1729 *pceltFetched = celt;
1730 This->pos += celt;
1732 return S_OK;
1735 static HRESULT WINAPI fnIEnumScript_Reset(
1736 IEnumScript* iface)
1738 EnumScript_impl *This = impl_from_IEnumScript( iface );
1740 TRACE("%p\n", This);
1742 This->pos = 0;
1743 return S_OK;
1746 static HRESULT WINAPI fnIEnumScript_Skip(
1747 IEnumScript* iface,
1748 ULONG celt)
1750 EnumScript_impl *This = impl_from_IEnumScript( iface );
1752 TRACE("%p %u\n", This, celt);
1754 if (celt >= This->total) return S_FALSE;
1756 This->pos += celt;
1757 return S_OK;
1760 static const IEnumScriptVtbl IEnumScript_vtbl =
1762 fnIEnumScript_QueryInterface,
1763 fnIEnumScript_AddRef,
1764 fnIEnumScript_Release,
1765 fnIEnumScript_Clone,
1766 fnIEnumScript_Next,
1767 fnIEnumScript_Reset,
1768 fnIEnumScript_Skip
1771 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1772 LANGID LangId, IEnumScript** ppEnumScript )
1774 EnumScript_impl *es;
1775 UINT i;
1777 TRACE("%p, %08x, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1779 if (!dwFlags) /* enumerate all available scripts */
1780 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1782 es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1783 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1784 es->ref = 1;
1785 es->pos = 0;
1786 /* do not enumerate unicode flavours */
1787 es->total = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
1788 es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1790 for (i = 0; i < es->total; i++)
1792 es->script_info[i].ScriptId = i;
1793 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1794 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1795 es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1796 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1797 es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1798 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1799 es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1802 TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
1804 *ppEnumScript = &es->IEnumScript_iface;
1806 return S_OK;
1809 /******************************************************************************/
1811 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1813 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1816 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1817 IMLangFontLink* iface,
1818 REFIID riid,
1819 void** ppvObject)
1821 MLang_impl *This = impl_from_IMLangFontLink( iface );
1822 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1825 static ULONG WINAPI fnIMLangFontLink_AddRef(
1826 IMLangFontLink* iface)
1828 MLang_impl *This = impl_from_IMLangFontLink( iface );
1829 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1832 static ULONG WINAPI fnIMLangFontLink_Release(
1833 IMLangFontLink* iface)
1835 MLang_impl *This = impl_from_IMLangFontLink( iface );
1836 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1839 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1840 IMLangFontLink* iface,
1841 WCHAR ch_src,
1842 DWORD* codepages)
1844 MLang_impl *This = impl_from_IMLangFontLink( iface );
1845 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
1848 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
1849 IMLangFontLink* iface,
1850 const WCHAR* src,
1851 LONG src_len,
1852 DWORD priority_cp,
1853 DWORD* codepages,
1854 LONG* ret_len)
1856 MLang_impl *This = impl_from_IMLangFontLink( iface );
1857 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
1858 codepages, ret_len);
1861 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
1862 IMLangFontLink* iface,
1863 UINT codepage,
1864 DWORD* codepages)
1866 MLang_impl *This = impl_from_IMLangFontLink( iface );
1867 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
1870 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
1871 IMLangFontLink* iface,
1872 DWORD codepages,
1873 UINT def_codepage,
1874 UINT* codepage)
1876 MLang_impl *This = impl_from_IMLangFontLink(iface);
1877 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
1878 def_codepage, codepage);
1881 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
1882 IMLangFontLink* iface,
1883 HDC hdc,
1884 HFONT hfont,
1885 DWORD* codepages)
1887 MLang_impl *This = impl_from_IMLangFontLink(iface);
1888 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
1891 static HRESULT WINAPI fnIMLangFontLink_MapFont(
1892 IMLangFontLink* iface,
1893 HDC hDC,
1894 DWORD dwCodePages,
1895 HFONT hSrcFont,
1896 HFONT* phDestFont)
1898 FIXME("\n");
1899 return E_NOTIMPL;
1902 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
1903 IMLangFontLink* iface,
1904 HFONT hFont)
1906 FIXME("\n");
1907 return E_NOTIMPL;
1910 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
1911 IMLangFontLink* iface)
1913 FIXME("\n");
1914 return E_NOTIMPL;
1918 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
1920 fnIMLangFontLink_QueryInterface,
1921 fnIMLangFontLink_AddRef,
1922 fnIMLangFontLink_Release,
1923 fnIMLangFontLink_GetCharCodePages,
1924 fnIMLangFontLink_GetStrCodePages,
1925 fnIMLangFontLink_CodePageToCodePages,
1926 fnIMLangFontLink_CodePagesToCodePage,
1927 fnIMLangFontLink_GetFontCodePages,
1928 fnIMLangFontLink_MapFont,
1929 fnIMLangFontLink_ReleaseFont,
1930 fnIMLangFontLink_ResetFontMapping,
1933 /******************************************************************************/
1935 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
1937 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
1940 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
1941 IMultiLanguage* iface,
1942 REFIID riid,
1943 void** obj)
1945 MLang_impl *This = impl_from_IMultiLanguage( iface );
1946 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
1949 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
1951 MLang_impl *This = impl_from_IMultiLanguage( iface );
1952 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
1955 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
1957 MLang_impl *This = impl_from_IMultiLanguage( iface );
1958 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
1961 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
1962 IMultiLanguage* iface,
1963 UINT* cp)
1965 MLang_impl *This = impl_from_IMultiLanguage( iface );
1966 TRACE("(%p, %p)\n", This, cp);
1967 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
1970 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
1971 IMultiLanguage* iface,
1972 UINT uiCodePage,
1973 PMIMECPINFO pCodePageInfo)
1975 UINT i, n;
1976 MLang_impl *This = impl_from_IMultiLanguage( iface );
1978 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
1980 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1982 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1984 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1986 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
1987 return S_OK;
1992 return S_FALSE;
1995 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
1996 IMultiLanguage* iface,
1997 UINT cp,
1998 UINT* family_cp)
2000 MLang_impl *This = impl_from_IMultiLanguage( iface );
2001 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2004 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2005 IMultiLanguage* iface,
2006 DWORD grfFlags,
2007 IEnumCodePage** ppEnumCodePage)
2009 MLang_impl *This = impl_from_IMultiLanguage( iface );
2011 TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
2013 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2016 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2017 IMultiLanguage* iface,
2018 BSTR Charset,
2019 PMIMECSETINFO pCharsetInfo)
2021 MLang_impl *This = impl_from_IMultiLanguage( iface );
2022 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2025 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2026 IMultiLanguage* iface,
2027 DWORD src_enc,
2028 DWORD dst_enc)
2030 MLang_impl *This = impl_from_IMultiLanguage( iface );
2031 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2034 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2035 IMultiLanguage* iface,
2036 DWORD* mode,
2037 DWORD src_enc,
2038 DWORD dst_enc,
2039 BYTE* src,
2040 UINT* src_size,
2041 BYTE* dest,
2042 UINT* dest_size)
2044 MLang_impl *This = impl_from_IMultiLanguage( iface );
2045 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2046 dst_enc, src, src_size, dest, dest_size);
2049 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2050 IMultiLanguage* iface,
2051 DWORD* mode,
2052 DWORD src_enc,
2053 CHAR* src,
2054 UINT* src_size,
2055 WCHAR* dest,
2056 UINT* dest_size)
2058 MLang_impl *This = impl_from_IMultiLanguage( iface );
2059 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2060 mode, src_enc, src, src_size, dest, dest_size);
2063 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2064 IMultiLanguage* iface,
2065 DWORD* mode,
2066 DWORD encoding,
2067 WCHAR* src,
2068 UINT* src_size,
2069 CHAR* dest,
2070 UINT* dest_size)
2072 MLang_impl *This = impl_from_IMultiLanguage(iface);
2073 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2074 mode, encoding, src, src_size, dest, dest_size);
2077 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2078 IMultiLanguage* iface)
2080 MLang_impl *This = impl_from_IMultiLanguage( iface );
2081 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2084 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2085 IMultiLanguage* iface,
2086 LCID lcid,
2087 BSTR* pbstrRfc1766)
2089 MLang_impl *This = impl_from_IMultiLanguage(iface);
2090 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2093 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2094 IMultiLanguage* iface,
2095 LCID* locale,
2096 BSTR rfc1766)
2098 MLang_impl *This = impl_from_IMultiLanguage(iface);
2099 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2102 /******************************************************************************/
2104 typedef struct tagEnumRfc1766_impl
2106 IEnumRfc1766 IEnumRfc1766_iface;
2107 LONG ref;
2108 RFC1766INFO *info;
2109 DWORD total, pos;
2110 } EnumRfc1766_impl;
2112 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2114 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2117 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2118 IEnumRfc1766 *iface,
2119 REFIID riid,
2120 void** ppvObject)
2122 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2124 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2126 if (IsEqualGUID(riid, &IID_IUnknown)
2127 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2129 IEnumRfc1766_AddRef(iface);
2130 TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
2131 *ppvObject = &This->IEnumRfc1766_iface;
2132 return S_OK;
2135 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2136 return E_NOINTERFACE;
2139 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2140 IEnumRfc1766 *iface)
2142 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2143 return InterlockedIncrement(&This->ref);
2146 static ULONG WINAPI fnIEnumRfc1766_Release(
2147 IEnumRfc1766 *iface)
2149 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2150 ULONG ref = InterlockedDecrement(&This->ref);
2152 TRACE("%p ref = %d\n", This, ref);
2153 if (ref == 0)
2155 TRACE("Destroying %p\n", This);
2156 HeapFree(GetProcessHeap(), 0, This->info);
2157 HeapFree(GetProcessHeap(), 0, This);
2159 return ref;
2162 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2163 IEnumRfc1766 *iface,
2164 IEnumRfc1766 **ppEnum)
2166 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2168 FIXME("%p %p\n", This, ppEnum);
2169 return E_NOTIMPL;
2172 static HRESULT WINAPI fnIEnumRfc1766_Next(
2173 IEnumRfc1766 *iface,
2174 ULONG celt,
2175 PRFC1766INFO rgelt,
2176 ULONG *pceltFetched)
2178 ULONG i;
2179 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2181 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
2183 if (!pceltFetched) return S_FALSE;
2184 *pceltFetched = 0;
2186 if (!rgelt) return S_FALSE;
2188 if (This->pos + celt > This->total)
2189 celt = This->total - This->pos;
2191 if (!celt) return S_FALSE;
2193 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2194 *pceltFetched = celt;
2195 This->pos += celt;
2197 for (i = 0; i < celt; i++)
2199 TRACE("#%u: %08x %s %s\n",
2200 i, rgelt[i].lcid,
2201 wine_dbgstr_w(rgelt[i].wszRfc1766),
2202 wine_dbgstr_w(rgelt[i].wszLocaleName));
2204 return S_OK;
2207 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2208 IEnumRfc1766 *iface)
2210 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2212 TRACE("%p\n", This);
2214 This->pos = 0;
2215 return S_OK;
2218 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2219 IEnumRfc1766 *iface,
2220 ULONG celt)
2222 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2224 TRACE("%p %u\n", This, celt);
2226 if (celt >= This->total) return S_FALSE;
2228 This->pos += celt;
2229 return S_OK;
2232 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2234 fnIEnumRfc1766_QueryInterface,
2235 fnIEnumRfc1766_AddRef,
2236 fnIEnumRfc1766_Release,
2237 fnIEnumRfc1766_Clone,
2238 fnIEnumRfc1766_Next,
2239 fnIEnumRfc1766_Reset,
2240 fnIEnumRfc1766_Skip
2243 struct enum_locales_data
2245 RFC1766INFO *info;
2246 DWORD total, allocated;
2249 static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
2251 WCHAR *end;
2252 struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
2253 RFC1766INFO *info;
2255 TRACE("%s\n", debugstr_w(locale));
2257 if (data->total >= data->allocated)
2259 data->allocated += 32;
2260 data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2261 if (!data->info) return FALSE;
2264 info = &data->info[data->total];
2266 info->lcid = strtolW(locale, &end, 16);
2267 if (*end) /* invalid number */
2268 return FALSE;
2270 info->wszRfc1766[0] = 0;
2271 lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
2273 info->wszLocaleName[0] = 0;
2274 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2275 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2277 data->total++;
2279 return TRUE;
2282 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2284 EnumRfc1766_impl *rfc;
2285 struct enum_locales_data data;
2287 TRACE("%04x, %p\n", LangId, ppEnum);
2289 rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2290 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2291 rfc->ref = 1;
2292 rfc->pos = 0;
2293 rfc->total = 0;
2295 data.total = 0;
2296 data.allocated = 160;
2297 data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2298 if (!data.info)
2300 HeapFree(GetProcessHeap(), 0, rfc);
2301 return E_OUTOFMEMORY;
2304 TlsSetValue(MLANG_tls_index, &data);
2305 EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
2306 TlsSetValue(MLANG_tls_index, NULL);
2308 TRACE("enumerated %d rfc1766 structures\n", data.total);
2310 if (!data.total)
2312 HeapFree(GetProcessHeap(), 0, data.info);
2313 HeapFree(GetProcessHeap(), 0, rfc);
2314 return E_FAIL;
2317 rfc->info = data.info;
2318 rfc->total = data.total;
2320 *ppEnum = &rfc->IEnumRfc1766_iface;
2321 return S_OK;
2324 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2325 IMultiLanguage *iface,
2326 IEnumRfc1766 **ppEnumRfc1766)
2328 MLang_impl *This = impl_from_IMultiLanguage( iface );
2330 TRACE("%p %p\n", This, ppEnumRfc1766);
2332 return EnumRfc1766_create(0, ppEnumRfc1766);
2335 /******************************************************************************/
2337 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2338 IMultiLanguage* iface,
2339 LCID Locale,
2340 PRFC1766INFO pRfc1766Info)
2342 LCTYPE type = LOCALE_SLANGUAGE;
2344 TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
2346 if (!pRfc1766Info)
2347 return E_INVALIDARG;
2349 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2350 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2351 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2353 if (!SUBLANGID(Locale))
2354 type = LOCALE_SENGLANGUAGE; /* suppress country */
2356 else
2358 if (!SUBLANGID(Locale)) {
2359 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2360 return E_FAIL;
2364 pRfc1766Info->lcid = Locale;
2365 pRfc1766Info->wszRfc1766[0] = 0;
2366 pRfc1766Info->wszLocaleName[0] = 0;
2368 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2369 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2370 return S_OK;
2372 /* Locale not supported */
2373 return E_INVALIDARG;
2376 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2377 IMultiLanguage* iface,
2378 UINT src_cp,
2379 UINT dst_cp,
2380 DWORD prop,
2381 IMLangConvertCharset** convert_charset)
2383 MLang_impl *This = impl_from_IMultiLanguage(iface);
2384 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2387 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2389 fnIMultiLanguage_QueryInterface,
2390 fnIMultiLanguage_AddRef,
2391 fnIMultiLanguage_Release,
2392 fnIMultiLanguage_GetNumberOfCodePageInfo,
2393 fnIMultiLanguage_GetCodePageInfo,
2394 fnIMultiLanguage_GetFamilyCodePage,
2395 fnIMultiLanguage_EnumCodePages,
2396 fnIMultiLanguage_GetCharsetInfo,
2397 fnIMultiLanguage_IsConvertible,
2398 fnIMultiLanguage_ConvertString,
2399 fnIMultiLanguage_ConvertStringToUnicode,
2400 fnIMultiLanguage_ConvertStringFromUnicode,
2401 fnIMultiLanguage_ConvertStringReset,
2402 fnIMultiLanguage_GetRfc1766FromLcid,
2403 fnIMultiLanguage_GetLcidFromRfc1766,
2404 fnIMultiLanguage_EnumRfc1766,
2405 fnIMultiLanguage_GetRfc1766Info,
2406 fnIMultiLanguage_CreateConvertCharset,
2410 /******************************************************************************/
2412 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2414 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2417 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2418 IMultiLanguage3* iface,
2419 REFIID riid,
2420 void** obj)
2422 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2424 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2426 if (IsEqualGUID(riid, &IID_IUnknown) ||
2427 IsEqualGUID(riid, &IID_IMultiLanguage))
2429 *obj = &This->IMultiLanguage_iface;
2431 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2432 IsEqualGUID(riid, &IID_IMLangFontLink))
2434 *obj = &This->IMLangFontLink_iface;
2436 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2438 *obj = &This->IMLangFontLink2_iface;
2440 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2441 IsEqualGUID(riid, &IID_IMultiLanguage3))
2443 *obj = &This->IMultiLanguage3_iface;
2445 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2447 *obj = &This->IMLangLineBreakConsole_iface;
2449 else
2451 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2452 *obj = NULL;
2453 return E_NOINTERFACE;
2456 IMultiLanguage3_AddRef(iface);
2457 return S_OK;
2460 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2462 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2463 return InterlockedIncrement(&This->ref);
2466 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2468 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2469 ULONG ref = InterlockedDecrement(&This->ref);
2471 TRACE("(%p)->(%d)\n", This, ref);
2472 if (ref == 0)
2474 HeapFree(GetProcessHeap(), 0, This);
2475 UnlockModule();
2478 return ref;
2481 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2482 IMultiLanguage3* iface,
2483 UINT* pcCodePage)
2485 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2487 TRACE("%p, %p\n", This, pcCodePage);
2489 if (!pcCodePage) return E_INVALIDARG;
2491 *pcCodePage = This->total_cp;
2492 return S_OK;
2495 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2497 CHARSETINFO csi;
2499 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2500 TCI_SRCCODEPAGE))
2501 mime_cp_info->bGDICharset = csi.ciCharset;
2502 else
2503 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2505 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2506 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2507 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2508 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
2509 mime_cp_info->wszDescription, sizeof(mime_cp_info->wszDescription)/sizeof(WCHAR));
2510 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
2511 mime_cp_info->wszWebCharset, sizeof(mime_cp_info->wszWebCharset)/sizeof(WCHAR));
2512 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
2513 mime_cp_info->wszHeaderCharset, sizeof(mime_cp_info->wszHeaderCharset)/sizeof(WCHAR));
2514 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
2515 mime_cp_info->wszBodyCharset, sizeof(mime_cp_info->wszBodyCharset)/sizeof(WCHAR));
2517 MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
2518 mime_cp_info->wszFixedWidthFont, sizeof(mime_cp_info->wszFixedWidthFont)/sizeof(WCHAR));
2519 MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
2520 mime_cp_info->wszProportionalFont, sizeof(mime_cp_info->wszProportionalFont)/sizeof(WCHAR));
2522 TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
2523 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2524 mime_cp_info->uiFamilyCodePage,
2525 wine_dbgstr_w(mime_cp_info->wszDescription),
2526 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2527 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2528 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2529 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2530 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2531 mime_cp_info->bGDICharset);
2534 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2535 IMultiLanguage3* iface,
2536 UINT uiCodePage,
2537 LANGID LangId,
2538 PMIMECPINFO pCodePageInfo)
2540 UINT i, n;
2541 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2543 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2545 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2547 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2549 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2551 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2552 return S_OK;
2557 return S_FALSE;
2560 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2561 IMultiLanguage3* iface,
2562 UINT uiCodePage,
2563 UINT* puiFamilyCodePage)
2565 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2568 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2569 IMultiLanguage3* iface,
2570 DWORD grfFlags,
2571 LANGID LangId,
2572 IEnumCodePage** ppEnumCodePage)
2574 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2576 TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2578 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2581 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2582 IMultiLanguage3* iface,
2583 BSTR Charset,
2584 PMIMECSETINFO pCharsetInfo)
2586 UINT i, n;
2587 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2589 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2591 if (!pCharsetInfo) return E_FAIL;
2593 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2595 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2597 WCHAR csetW[MAX_MIMECSET_NAME];
2599 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
2600 if (!lstrcmpiW(Charset, csetW))
2602 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2603 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2604 strcpyW(pCharsetInfo->wszCharset, csetW);
2605 return S_OK;
2607 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2609 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2610 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2611 strcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2612 return S_OK;
2617 /* FIXME:
2618 * Since we do not support charsets like iso-2022-jp and do not have
2619 * them in our database as a primary (web_charset) encoding this loop
2620 * does an attempt to 'approximate' charset name by header_charset.
2622 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2624 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2626 WCHAR csetW[MAX_MIMECSET_NAME];
2628 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
2629 if (!lstrcmpiW(Charset, csetW))
2631 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2632 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2633 strcpyW(pCharsetInfo->wszCharset, csetW);
2634 return S_OK;
2639 return E_FAIL;
2642 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2643 IMultiLanguage3* iface,
2644 DWORD dwSrcEncoding,
2645 DWORD dwDstEncoding)
2647 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2650 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2651 IMultiLanguage3* iface,
2652 DWORD* pdwMode,
2653 DWORD dwSrcEncoding,
2654 DWORD dwDstEncoding,
2655 BYTE* pSrcStr,
2656 UINT* pcSrcSize,
2657 BYTE* pDstStr,
2658 UINT* pcDstSize)
2660 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2661 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2664 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2665 IMultiLanguage3* iface,
2666 DWORD* pdwMode,
2667 DWORD dwEncoding,
2668 CHAR* pSrcStr,
2669 UINT* pcSrcSize,
2670 WCHAR* pDstStr,
2671 UINT* pcDstSize)
2673 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2674 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2677 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2678 IMultiLanguage3* iface,
2679 DWORD* pdwMode,
2680 DWORD dwEncoding,
2681 WCHAR* pSrcStr,
2682 UINT* pcSrcSize,
2683 CHAR* pDstStr,
2684 UINT* pcDstSize)
2686 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2687 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2690 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2691 IMultiLanguage3* iface)
2693 FIXME("\n");
2694 return E_NOTIMPL;
2697 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2698 IMultiLanguage3* iface,
2699 LCID lcid,
2700 BSTR* pbstrRfc1766)
2702 WCHAR buf[MAX_RFC1766_NAME];
2704 TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
2705 if (!pbstrRfc1766)
2706 return E_INVALIDARG;
2708 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2710 *pbstrRfc1766 = SysAllocString( buf );
2711 return S_OK;
2713 return E_FAIL;
2716 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2717 IMultiLanguage3* iface,
2718 LCID* pLocale,
2719 BSTR bstrRfc1766)
2721 HRESULT hr;
2722 IEnumRfc1766 *rfc1766;
2724 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2726 if (!pLocale || !bstrRfc1766)
2727 return E_INVALIDARG;
2729 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2730 if (FAILED(hr))
2731 return hr;
2733 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2735 IEnumRfc1766_Release(rfc1766);
2736 return hr;
2739 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2740 IMultiLanguage3* iface,
2741 LANGID LangId,
2742 IEnumRfc1766** ppEnumRfc1766)
2744 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2746 TRACE("%p %p\n", This, ppEnumRfc1766);
2748 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2751 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2752 IMultiLanguage3* iface,
2753 LCID Locale,
2754 LANGID LangId,
2755 PRFC1766INFO pRfc1766Info)
2757 static LANGID last_lang = -1;
2758 LCTYPE type = LOCALE_SLANGUAGE;
2760 TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2762 if (!pRfc1766Info)
2763 return E_INVALIDARG;
2765 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2766 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2767 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2769 if (!SUBLANGID(Locale))
2770 type = LOCALE_SENGLANGUAGE; /* suppress country */
2772 else
2774 if (!SUBLANGID(Locale)) {
2775 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2776 return E_FAIL;
2780 pRfc1766Info->lcid = Locale;
2781 pRfc1766Info->wszRfc1766[0] = 0;
2782 pRfc1766Info->wszLocaleName[0] = 0;
2784 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2785 (last_lang != LangId)) {
2786 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2787 last_lang = LangId;
2790 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2791 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2792 return S_OK;
2794 /* Locale not supported */
2795 return E_INVALIDARG;
2798 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2799 IMultiLanguage3* iface,
2800 UINT src_cp,
2801 UINT dst_cp,
2802 DWORD prop,
2803 IMLangConvertCharset** convert_charset)
2805 HRESULT hr;
2807 TRACE("(%u %u 0x%08x %p)\n", src_cp, dst_cp, prop, convert_charset);
2809 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2810 if (FAILED(hr)) return hr;
2812 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2815 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2816 IMultiLanguage3* iface,
2817 DWORD* pdwMode,
2818 DWORD dwFlag,
2819 WCHAR* lpFallBack,
2820 DWORD dwSrcEncoding,
2821 DWORD dwDstEncoding,
2822 IStream* pstmIn,
2823 IStream* pstmOut)
2825 char *src, *dst = NULL;
2826 INT srclen, dstlen;
2827 STATSTG stat;
2828 HRESULT hr;
2830 TRACE("%p %0x8 %s %u %u %p %p\n",
2831 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2833 FIXME("dwFlag and lpFallBack not handled\n");
2835 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2836 if (FAILED(hr)) return hr;
2838 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
2839 if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
2841 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
2842 if (FAILED(hr)) goto exit;
2844 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
2845 if (FAILED(hr)) goto exit;
2847 if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
2849 hr = E_OUTOFMEMORY;
2850 goto exit;
2852 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
2853 if (FAILED(hr)) goto exit;
2855 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
2857 exit:
2858 HeapFree(GetProcessHeap(), 0, src);
2859 HeapFree(GetProcessHeap(), 0, dst);
2860 return hr;
2863 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
2864 IMultiLanguage3* iface,
2865 DWORD* pdwMode,
2866 DWORD dwEncoding,
2867 CHAR* pSrcStr,
2868 UINT* pcSrcSize,
2869 WCHAR* pDstStr,
2870 UINT* pcDstSize,
2871 DWORD dwFlag,
2872 WCHAR* lpFallBack)
2874 if (dwFlag || lpFallBack)
2875 FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
2876 dwFlag, dwFlag, lpFallBack);
2878 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2879 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2882 /*****************************************************************************
2883 * MultiLanguage2::ConvertStringToUnicodeEx
2885 * Translates the multibyte string from the specified code page to Unicode.
2887 * PARAMS
2888 * see ConvertStringToUnicode
2889 * dwFlag
2890 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
2891 * instead unconvertible characters.
2893 * RETURNS
2894 * S_OK Success.
2895 * S_FALSE The conversion is not supported.
2896 * E_FAIL Some error has occurred.
2898 * TODO: handle dwFlag and lpFallBack
2900 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
2901 IMultiLanguage3* This,
2902 DWORD* pdwMode,
2903 DWORD dwEncoding,
2904 WCHAR* pSrcStr,
2905 UINT* pcSrcSize,
2906 CHAR* pDstStr,
2907 UINT* pcDstSize,
2908 DWORD dwFlag,
2909 WCHAR* lpFallBack)
2911 FIXME("\n");
2912 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2913 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2916 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
2917 IMultiLanguage3* iface,
2918 DWORD dwFlag,
2919 DWORD dwPrefWinCodePage,
2920 IStream* pstmIn,
2921 DetectEncodingInfo* lpEncoding,
2922 INT* pnScores)
2924 FIXME("\n");
2925 return E_NOTIMPL;
2928 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
2929 IMultiLanguage3* iface,
2930 DWORD dwFlag,
2931 DWORD dwPrefWinCodePage,
2932 CHAR* pSrcStr,
2933 INT* pcSrcSize,
2934 DetectEncodingInfo* lpEncoding,
2935 INT* pnScores)
2937 FIXME("\n");
2938 return E_NOTIMPL;
2941 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
2942 IMultiLanguage3* iface,
2943 UINT uiCodePage,
2944 HWND hwnd)
2946 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
2949 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
2950 IMultiLanguage3* iface,
2951 UINT uiCodePage,
2952 LCID lcid,
2953 LPWSTR lpWideCharStr,
2954 int cchWideChar)
2956 /* Find first instance */
2957 unsigned int i,n;
2959 TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
2960 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2962 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2964 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2966 MultiByteToWideChar(CP_ACP, 0,
2967 mlang_data[i].mime_cp_info[n].description,
2968 -1, lpWideCharStr, cchWideChar);
2969 return S_OK;
2974 return S_FALSE;
2977 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
2978 IMultiLanguage3* iface,
2979 UINT uiCodePage)
2981 TRACE("%u\n", uiCodePage);
2983 /* FIXME: the installable set is usually larger than the set of valid codepages */
2984 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
2987 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
2988 IMultiLanguage3* iface,
2989 MIMECONTF dwSource)
2991 FIXME("0x%08x\n", dwSource);
2992 return S_OK;
2995 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
2996 IMultiLanguage3* iface,
2997 UINT* pnScripts)
2999 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3001 TRACE("%p %p\n", This, pnScripts);
3003 if (!pnScripts) return S_FALSE;
3005 *pnScripts = This->total_scripts;
3006 return S_OK;
3009 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3010 IMultiLanguage3* iface,
3011 DWORD dwFlags,
3012 LANGID LangId,
3013 IEnumScript** ppEnumScript)
3015 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3017 TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3019 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3022 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3023 IMultiLanguage3* iface,
3024 UINT uiCodePage,
3025 HWND hwnd,
3026 DWORD dwfIODControl)
3028 unsigned int i;
3029 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3031 TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
3033 /* quick check for kernel32 supported code pages */
3034 if (IsValidCodePage(uiCodePage))
3035 return S_OK;
3037 /* check for mlang supported code pages */
3038 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3040 UINT n;
3041 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3043 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3044 return S_OK;
3048 if (dwfIODControl != CPIOD_PEEK)
3049 FIXME("Request to install codepage language pack not handled\n");
3051 return S_FALSE;
3054 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3055 IMultiLanguage3 *iface,
3056 DWORD dwFlags,
3057 LPCWSTR lpWideCharStr,
3058 UINT cchWideChar,
3059 UINT *puiPreferredCodePages,
3060 UINT nPreferredCodePages,
3061 UINT *puiDetectedCodePages,
3062 UINT *pnDetectedCodePages,
3063 WCHAR *lpSpecialChar)
3065 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3067 FIXME("(%p)->(%08x %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3068 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3069 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3070 debugstr_w(lpSpecialChar));
3072 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3073 return E_INVALIDARG;
3075 puiDetectedCodePages[0] = CP_UTF8;
3076 *pnDetectedCodePages = 1;
3077 return S_OK;
3080 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3081 IMultiLanguage3 *iface,
3082 DWORD dwFlags,
3083 IStream *pStrIn,
3084 UINT *puiPreferredCodePages,
3085 UINT nPreferredCodePages,
3086 UINT *puiDetectedCodePages,
3087 UINT *pnDetectedCodePages,
3088 WCHAR *lpSpecialChar)
3090 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3092 FIXME("(%p)->(%08x %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3093 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3094 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3095 debugstr_w(lpSpecialChar));
3097 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3098 return E_INVALIDARG;
3100 puiDetectedCodePages[0] = CP_UTF8;
3101 *pnDetectedCodePages = 1;
3102 return S_OK;
3105 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3107 fnIMultiLanguage3_QueryInterface,
3108 fnIMultiLanguage3_AddRef,
3109 fnIMultiLanguage3_Release,
3110 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3111 fnIMultiLanguage3_GetCodePageInfo,
3112 fnIMultiLanguage3_GetFamilyCodePage,
3113 fnIMultiLanguage3_EnumCodePages,
3114 fnIMultiLanguage3_GetCharsetInfo,
3115 fnIMultiLanguage3_IsConvertible,
3116 fnIMultiLanguage3_ConvertString,
3117 fnIMultiLanguage3_ConvertStringToUnicode,
3118 fnIMultiLanguage3_ConvertStringFromUnicode,
3119 fnIMultiLanguage3_ConvertStringReset,
3120 fnIMultiLanguage3_GetRfc1766FromLcid,
3121 fnIMultiLanguage3_GetLcidFromRfc1766,
3122 fnIMultiLanguage3_EnumRfc1766,
3123 fnIMultiLanguage3_GetRfc1766Info,
3124 fnIMultiLanguage3_CreateConvertCharset,
3125 fnIMultiLanguage3_ConvertStringInIStream,
3126 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3127 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3128 fnIMultiLanguage3_DetectCodepageInIStream,
3129 fnIMultiLanguage3_DetectInputCodepage,
3130 fnIMultiLanguage3_ValidateCodePage,
3131 fnIMultiLanguage3_GetCodePageDescription,
3132 fnIMultiLanguage3_IsCodePageInstallable,
3133 fnIMultiLanguage3_SetMimeDBSource,
3134 fnIMultiLanguage3_GetNumberOfScripts,
3135 fnIMultiLanguage3_EnumScripts,
3136 fnIMultiLanguage3_ValidateCodePageEx,
3137 fnIMultiLanguage3_DetectOutboundCodePage,
3138 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3141 /******************************************************************************/
3143 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3145 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3148 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3149 IMLangFontLink2 * iface,
3150 REFIID riid,
3151 void** ppvObject)
3153 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3154 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3157 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3159 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3160 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3163 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3165 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3166 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3169 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3170 WCHAR ch_src, DWORD *ret_codepages)
3172 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3173 unsigned int i;
3175 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3177 *ret_codepages = 0;
3179 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3181 BOOL used_dc;
3182 CHAR buf;
3184 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3185 &ch_src, 1, &buf, 1, NULL, &used_dc);
3187 /* If default char is not used, current codepage include the given symbol */
3188 if (!used_dc)
3190 DWORD codepages;
3192 IMLangFontLink2_CodePageToCodePages(iface,
3193 mlang_data[i].family_codepage, &codepages);
3194 *ret_codepages |= codepages;
3197 return S_OK;
3200 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3201 const WCHAR *src, LONG src_len, DWORD priority_cp,
3202 DWORD *codepages, LONG *ret_len)
3204 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3205 LONG i;
3206 DWORD cps = 0;
3208 TRACE("(%p)->(%s:%d %x %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3209 codepages, ret_len);
3211 if (codepages) *codepages = 0;
3212 if (ret_len) *ret_len = 0;
3214 if (!src || !src_len || src_len < 0)
3215 return E_INVALIDARG;
3217 for (i = 0; i < src_len; i++)
3219 DWORD cp;
3220 HRESULT ret;
3222 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3223 if (ret != S_OK) return E_FAIL;
3225 if (!cps) cps = cp;
3226 else cps &= cp;
3228 /* FIXME: not tested */
3229 if (priority_cp & cps) break;
3232 if (codepages) *codepages = cps;
3233 if (ret_len) *ret_len = min( i + 1, src_len );
3234 return S_OK;
3237 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3238 UINT codepage,
3239 DWORD *codepages)
3241 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3242 CHARSETINFO cs;
3243 BOOL rc;
3245 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3247 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3248 if (rc)
3250 *codepages = cs.fs.fsCsb[0];
3251 TRACE("resulting codepages 0x%x\n", *codepages);
3252 return S_OK;
3255 TRACE("codepage not found\n");
3256 *codepages = 0;
3257 return E_FAIL;
3260 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3261 DWORD codepages, UINT def_codepage, UINT *codepage)
3263 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3264 DWORD mask = 0;
3265 CHARSETINFO cs;
3266 BOOL rc;
3267 UINT i;
3269 TRACE("(%p)->(0x%x %u %p)\n", This, codepages, def_codepage, codepage);
3271 *codepage = 0;
3273 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3274 if (rc && (codepages & cs.fs.fsCsb[0]))
3276 TRACE("Found Default Codepage\n");
3277 *codepage = def_codepage;
3278 return S_OK;
3281 for (i = 0; i < 32; i++)
3283 mask = 1 << i;
3284 if (codepages & mask)
3286 DWORD Csb[2];
3287 Csb[0] = mask;
3288 Csb[1] = 0x0;
3289 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3290 if (!rc)
3291 continue;
3293 TRACE("Falling back to least significant found CodePage %u\n",
3294 cs.ciACP);
3295 *codepage = cs.ciACP;
3296 return S_OK;
3300 TRACE("no codepage found\n");
3301 return E_FAIL;
3304 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3305 HDC hdc, HFONT hfont, DWORD *codepages)
3307 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3308 FONTSIGNATURE fontsig;
3309 HFONT old_font;
3311 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3313 old_font = SelectObject(hdc, hfont);
3314 GetTextCharsetInfo(hdc, &fontsig, 0);
3315 SelectObject(hdc, old_font);
3317 *codepages = fontsig.fsCsb[0];
3318 TRACE("ret 0x%x\n", fontsig.fsCsb[0]);
3320 return S_OK;
3323 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3324 HFONT hFont)
3326 FIXME("(%p)->%p\n",This, hFont);
3327 return E_NOTIMPL;
3330 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3332 FIXME("(%p)->\n",This);
3333 return E_NOTIMPL;
3336 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3337 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3339 FIXME("(%p)->%p %i %s %p\n",This, hDC, dwCodePages, debugstr_wn(&chSrc,1), pFont);
3340 return E_NOTIMPL;
3343 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3344 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3346 DWORD size;
3347 GLYPHSET *gs;
3349 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3351 if (!puiRanges) return E_INVALIDARG;
3352 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3353 if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3355 GetFontUnicodeRanges(hDC, gs);
3356 *puiRanges = gs->cRanges;
3357 if (pUranges)
3359 UINT i;
3360 for (i = 0; i < gs->cRanges; i++)
3362 if (i >= *puiRanges) break;
3363 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3364 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3366 *puiRanges = i;
3368 HeapFree(GetProcessHeap(), 0, gs);
3369 return S_OK;
3372 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3373 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3374 SCRIPTFONTINFO *pScriptFont)
3376 UINT i, j;
3378 TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3380 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3382 for (i = 0, j = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3384 if (sid == mlang_data[i].sid)
3386 if (pScriptFont)
3388 if (j >= *puiFonts) break;
3390 pScriptFont[j].scripts = 1 << mlang_data[i].sid;
3391 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3393 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
3394 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3396 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3398 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
3399 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3402 j++;
3405 *puiFonts = j;
3406 return S_OK;
3409 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3410 UINT uiCodePage, SCRIPT_ID *pSid)
3412 UINT i;
3414 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3416 if (uiCodePage == CP_UNICODE) return E_FAIL;
3418 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3420 if (uiCodePage == mlang_data[i].family_codepage)
3422 if (pSid) *pSid = mlang_data[i].sid;
3423 return S_OK;
3426 return E_FAIL;
3429 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3431 fnIMLangFontLink2_QueryInterface,
3432 fnIMLangFontLink2_AddRef,
3433 fnIMLangFontLink2_Release,
3434 fnIMLangFontLink2_GetCharCodePages,
3435 fnIMLangFontLink2_GetStrCodePages,
3436 fnIMLangFontLink2_CodePageToCodePages,
3437 fnIMLangFontLink2_CodePagesToCodePage,
3438 fnIMLangFontLink2_GetFontCodePages,
3439 fnIMLangFontLink2_ReleaseFont,
3440 fnIMLangFontLink2_ResetFontMapping,
3441 fnIMLangFontLink2_MapFont,
3442 fnIMLangFontLink2_GetFontUnicodeRanges,
3443 fnIMLangFontLink2_GetScriptFontInfo,
3444 fnIMLangFontLink2_CodePageToScriptID
3447 /******************************************************************************/
3449 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3451 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3454 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3455 IMLangLineBreakConsole* iface,
3456 REFIID riid,
3457 void** ppvObject)
3459 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3460 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3463 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3464 IMLangLineBreakConsole* iface )
3466 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3467 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3470 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3471 IMLangLineBreakConsole* iface )
3473 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3474 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3477 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3478 IMLangLineBreakConsole* iface,
3479 IMLangString* pSrcMLStr,
3480 LONG lSrcPos,
3481 LONG lSrcLen,
3482 LONG cMinColumns,
3483 LONG cMaxColumns,
3484 LONG* plLineLen,
3485 LONG* plSkipLen)
3487 FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3488 return E_NOTIMPL;
3491 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3492 IMLangLineBreakConsole* iface,
3493 LCID locale,
3494 const WCHAR* pszSrc,
3495 LONG cchSrc,
3496 LONG cMaxColumns,
3497 LONG* pcchLine,
3498 LONG* pcchSkip )
3500 FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3502 *pcchLine = cchSrc;
3503 *pcchSkip = 0;
3504 return S_OK;
3507 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3508 IMLangLineBreakConsole* iface,
3509 LCID locale,
3510 UINT uCodePage,
3511 const CHAR* pszSrc,
3512 LONG cchSrc,
3513 LONG cMaxColumns,
3514 LONG* pcchLine,
3515 LONG* pcchSkip)
3517 LONG i, line = cchSrc, skip = 0;
3519 FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3521 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3523 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3525 if (pszSrc[i] == ' ')
3527 while (i >= 0 && pszSrc[i] == ' ')
3529 i--;
3530 line--;
3531 skip++;
3533 break;
3537 *pcchLine = line;
3538 *pcchSkip = skip;
3539 return S_OK;
3542 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3544 fnIMLangLineBreakConsole_QueryInterface,
3545 fnIMLangLineBreakConsole_AddRef,
3546 fnIMLangLineBreakConsole_Release,
3547 fnIMLangLineBreakConsole_BreakLineML,
3548 fnIMLangLineBreakConsole_BreakLineW,
3549 fnIMLangLineBreakConsole_BreakLineA
3552 struct convert_charset {
3553 IMLangConvertCharset IMLangConvertCharset_iface;
3554 LONG ref;
3556 UINT src_cp;
3557 UINT dst_cp;
3560 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3562 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3565 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3567 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3569 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3571 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3573 *obj = &This->IMLangConvertCharset_iface;
3574 IMLangConvertCharset_AddRef(iface);
3575 return S_OK;
3578 *obj = NULL;
3579 return E_NOINTERFACE;
3582 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3584 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3585 ULONG ref = InterlockedIncrement(&This->ref);
3586 TRACE("(%p)->(%u)\n", This, ref);
3587 return ref;
3590 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3592 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3593 ULONG ref = InterlockedDecrement(&This->ref);
3595 TRACE("(%p)->(%u)\n", This, ref);
3596 if (!ref)
3598 HeapFree(GetProcessHeap(), 0, This);
3599 UnlockModule();
3602 return ref;
3605 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3606 UINT src_cp, UINT dst_cp, DWORD prop)
3608 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3610 TRACE("(%p)->(%u %u 0x%08x)\n", This, src_cp, dst_cp, prop);
3612 prop &= ~MLCONVCHARF_USEDEFCHAR;
3613 if (prop)
3614 FIXME("property 0x%08x not supported\n", prop);
3616 This->src_cp = src_cp;
3617 This->dst_cp = dst_cp;
3619 return S_OK;
3622 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3624 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3626 TRACE("(%p)->(%p)\n", This, src_cp);
3628 if (!src_cp) return E_INVALIDARG;
3629 *src_cp = This->src_cp;
3630 return S_OK;
3633 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3635 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3637 TRACE("(%p)->(%p)\n", This, dst_cp);
3639 if (!dst_cp) return E_INVALIDARG;
3640 *dst_cp = This->dst_cp;
3641 return S_OK;
3644 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3646 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3647 FIXME("(%p)->(%p): stub\n", This, prop);
3648 return E_NOTIMPL;
3651 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3652 UINT *src_size, BYTE *dest, UINT *dest_size)
3654 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3655 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3656 return E_NOTIMPL;
3659 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3660 UINT *src_size, WCHAR *dest, UINT *dest_size)
3662 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3663 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3664 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3667 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3668 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3670 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3671 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3672 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3675 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3677 MLangConvertCharset_QueryInterface,
3678 MLangConvertCharset_AddRef,
3679 MLangConvertCharset_Release,
3680 MLangConvertCharset_Initialize,
3681 MLangConvertCharset_GetSourceCodePage,
3682 MLangConvertCharset_GetDestinationCodePage,
3683 MLangConvertCharset_GetProperty,
3684 MLangConvertCharset_DoConversion,
3685 MLangConvertCharset_DoConversionToUnicode,
3686 MLangConvertCharset_DoConversionFromUnicode
3689 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3691 MLang_impl *mlang;
3692 UINT i;
3694 TRACE("Creating MultiLanguage object\n");
3696 if( pUnkOuter )
3697 return CLASS_E_NOAGGREGATION;
3699 mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3700 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3701 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3702 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3703 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3704 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3706 mlang->total_cp = 0;
3707 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3708 mlang->total_cp += mlang_data[i].number_of_cp;
3710 /* do not enumerate unicode flavours */
3711 mlang->total_scripts = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
3713 mlang->ref = 1;
3714 *ppObj = &mlang->IMultiLanguage_iface;
3715 TRACE("returning %p\n", mlang);
3717 LockModule();
3719 return S_OK;
3722 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3724 struct convert_charset *convert;
3726 if (outer)
3727 return CLASS_E_NOAGGREGATION;
3729 *obj = NULL;
3731 convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3732 if (!convert) return E_OUTOFMEMORY;
3734 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3735 convert->ref = 1;
3737 *obj = &convert->IMLangConvertCharset_iface;
3739 LockModule();
3741 return S_OK;
3744 /******************************************************************************/
3746 HRESULT WINAPI DllCanUnloadNow(void)
3748 return dll_count == 0 ? S_OK : S_FALSE;
3752 /***********************************************************************
3753 * DllRegisterServer (MLANG.@)
3755 HRESULT WINAPI DllRegisterServer(void)
3757 return __wine_register_resources( instance );
3760 /***********************************************************************
3761 * DllUnregisterServer (MLANG.@)
3763 HRESULT WINAPI DllUnregisterServer(void)
3765 return __wine_unregister_resources( instance );
3768 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
3770 if (!unknown) return E_INVALIDARG;
3772 FIXME("%p: stub\n", unknown);
3774 return S_FALSE;