Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / dll / win32 / mlang / mlang.c
1 /*
2 * MLANG Class Factory
3 *
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2003,2004 Mike McCormack
6 * Copyright 2004,2005 Dmitry Timoshkov
7 * Copyright 2009 Detlef Riekenberg
8 *
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.
13 *
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.
18 *
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
22 */
23
24 #define WIN32_NO_STATUS
25 #define _INC_WINDOWS
26
27 #include <config.h>
28
29 #include <stdarg.h>
30 //#include <stdio.h>
31
32 #define COBJMACROS
33
34 #include <windef.h>
35 #include <winbase.h>
36 #include <wingdi.h>
37 //#include "winuser.h"
38 #include <ole2.h>
39 //#include "objbase.h"
40 #include <rpcproxy.h>
41 #include <mlang.h>
42 #include <mimeole.h>
43
44 #include <wine/unicode.h>
45 #include <wine/debug.h>
46
47 WINE_DEFAULT_DEBUG_CHANNEL(mlang);
48
49 //#include "initguid.h"
50
51 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
52 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj);
53 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum);
54
55 static HINSTANCE instance;
56 static DWORD MLANG_tls_index; /* to store various per thead data */
57
58 /* FIXME:
59 * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
60 * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
61 */
62
63 typedef struct
64 {
65 const char *description;
66 UINT cp;
67 DWORD flags;
68 const char *web_charset;
69 const char *header_charset;
70 const char *body_charset;
71 const WCHAR *alias;
72 } MIME_CP_INFO;
73
74 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
75 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
76
77 static const MIME_CP_INFO arabic_cp[] =
78 {
79 { "Arabic (864)",
80 864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
81 MIMECONTF_MIME_LATEST,
82 "ibm864", "ibm864", "ibm864" },
83 { "Arabic (1006)",
84 1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
85 MIMECONTF_MIME_LATEST,
86 "ibm1006", "ibm1006", "ibm1006" },
87 { "Arabic (Windows)",
88 1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
89 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
90 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
91 "windows-1256", "windows-1256", "windows-1256" },
92 { "Arabic (ISO)",
93 28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
94 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
95 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
96 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
97 "iso-8859-6", "iso-8859-6", "iso-8859-6" }
98 };
99 static const MIME_CP_INFO baltic_cp[] =
100 {
101 { "Baltic (DOS)",
102 775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
103 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
104 "ibm775", "ibm775", "ibm775" },
105 { "Baltic (Windows)",
106 1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
107 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
108 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
109 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
110 "windows-1257", "windows-1257", "windows-1257" },
111 { "Baltic (ISO)",
112 28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
113 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
114 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
115 MIMECONTF_MIME_LATEST,
116 "iso-8859-4", "iso-8859-4", "iso-8859-4" },
117 { "Estonian (ISO)",
118 28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
119 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
120 "iso-8859-13", "iso-8859-13", "iso-8859-13" }
121 };
122 static const MIME_CP_INFO chinese_simplified_cp[] =
123 {
124 { "Chinese Simplified (GB2312)",
125 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
126 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
127 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
128 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
129 "gb2312", "gb2312", "gb2312" },
130 { "Chinese Simplified (GBK)",
131 936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
132 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
133 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
134 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
135 "gbk", "gbk", "gbk" }
136 };
137 static const MIME_CP_INFO chinese_traditional_cp[] =
138 {
139 { "Chinese Traditional (Big5)",
140 950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
141 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
142 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
143 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
144 "big5", "big5", "big5" }
145 };
146 static const MIME_CP_INFO central_european_cp[] =
147 {
148 { "Central European (DOS)",
149 852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
150 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
151 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
152 "ibm852", "ibm852", "ibm852" },
153 { "Central European (Windows)",
154 1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
155 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
156 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
157 MIMECONTF_MIME_LATEST,
158 "windows-1250", "windows-1250", "windows-1250" },
159 { "Central European (Mac)",
160 10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
161 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
162 "x-mac-ce", "x-mac-ce", "x-mac-ce" },
163 { "Central European (ISO)",
164 28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
165 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
166 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
167 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
168 "iso-8859-2", "iso-8859-2", "iso-8859-2" }
169 };
170 static const MIME_CP_INFO cyrillic_cp[] =
171 {
172 { "OEM Cyrillic",
173 855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
174 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
175 "ibm855", "ibm855", "ibm855" },
176 { "Cyrillic (DOS)",
177 866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
178 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
179 MIMECONTF_MIME_LATEST,
180 "cp866", "cp866", "cp866" },
181 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
182 { "Cyrillic (KOI8-R)",
183 878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
184 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
185 "koi8-r", "koi8-r", "koi8-r" },
186 #endif
187 { "Cyrillic (Windows)",
188 1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
189 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
190 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
191 "windows-1251", "windows-1251", "windows-1251" },
192 { "Cyrillic (Mac)",
193 10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
194 MIMECONTF_MIME_LATEST,
195 "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
196 { "Cyrillic (KOI8-R)",
197 20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
198 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
199 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
200 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
201 "koi8-r", "koi8-r", "koi8-r" },
202 { "Cyrillic (KOI8-U)",
203 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
204 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
205 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
206 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
207 "koi8-u", "koi8-u", "koi8-u" },
208 { "Cyrillic (ISO)",
209 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
210 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
211 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
212 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
213 "iso-8859-5", "iso-8859-5", "iso-8859-5" }
214 };
215 static const MIME_CP_INFO greek_cp[] =
216 {
217 { "Greek (DOS)",
218 737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
219 MIMECONTF_MIME_LATEST,
220 "ibm737", "ibm737", "ibm737" },
221 { "Greek, Modern (DOS)",
222 869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
223 MIMECONTF_MIME_LATEST,
224 "ibm869", "ibm869", "ibm869" },
225 { "IBM EBCDIC (Greek Modern)",
226 875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
227 MIMECONTF_MIME_LATEST,
228 "cp875", "cp875", "cp875" },
229 { "Greek (Windows)",
230 1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
231 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
232 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
233 "windows-1253", "windows-1253", "windows-1253" },
234 { "Greek (Mac)",
235 10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
236 MIMECONTF_MIME_LATEST,
237 "x-mac-greek", "x-mac-greek", "x-mac-greek" },
238 { "Greek (ISO)",
239 28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
240 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
241 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
242 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
243 "iso-8859-7", "iso-8859-7", "iso-8859-7" }
244 };
245 static const MIME_CP_INFO hebrew_cp[] =
246 {
247 { "Hebrew (424)",
248 424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
249 MIMECONTF_MIME_LATEST,
250 "ibm424", "ibm424", "ibm424" },
251 { "Hebrew (856)",
252 856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
253 MIMECONTF_MIME_LATEST,
254 "cp856", "cp856", "cp856" },
255 { "Hebrew (DOS)",
256 862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
257 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
258 MIMECONTF_MIME_LATEST,
259 "dos-862", "dos-862", "dos-862" },
260 { "Hebrew (Windows)",
261 1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
262 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
263 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
264 "windows-1255", "windows-1255", "windows-1255" },
265 { "Hebrew (ISO-Visual)",
266 28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
267 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
268 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
269 "iso-8859-8", "iso-8859-8", "iso-8859-8" }
270 };
271 static const MIME_CP_INFO japanese_cp[] =
272 {
273 { "Japanese (Auto-Select)",
274 50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
275 MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
276 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
277 "_autodetect", "_autodetect", "_autodetect" },
278 { "Japanese (EUC)",
279 51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
280 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
281 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
282 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
283 "euc-jp", "euc-jp", "euc-jp" },
284 { "Japanese (JIS)",
285 50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
286 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
287 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
288 MIMECONTF_MIME_IE4,
289 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
290 { "Japanese (JIS 0208-1990 and 0212-1990)",
291 20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
292 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
293 "EUC-JP","EUC-JP","EUC-JP"},
294 { "Japanese (JIS-Allow 1 byte Kana)",
295 50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
296 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
297 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
298 "csISO2022JP","iso-2022-jp","iso-2022-jp"},
299 { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
300 50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
301 MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
302 "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
303 { "Japanese (Mac)",
304 10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
305 MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
306 "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
307 { "Japanese (Shift-JIS)",
308 932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
309 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
310 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
311 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
312 "shift_jis", "iso-2022-jp", "iso-2022-jp" }
313 };
314 static const MIME_CP_INFO korean_cp[] =
315 {
316 { "Korean",
317 949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
318 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
319 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
320 MIMECONTF_MIME_LATEST,
321 "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
322 };
323 static const MIME_CP_INFO thai_cp[] =
324 {
325 { "Thai (Windows)",
326 874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
327 "ibm-thai", "ibm-thai", "ibm-thai" }
328 };
329 static const MIME_CP_INFO turkish_cp[] =
330 {
331 { "Turkish (DOS)",
332 857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
333 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
334 "ibm857", "ibm857", "ibm857" },
335 { "IBM EBCDIC (Turkish Latin-5)",
336 1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
337 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
338 "ibm1026", "ibm1026", "ibm1026" },
339 { "Turkish (Windows)",
340 1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
341 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
342 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
343 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
344 "windows-1254", "windows-1254", "windows-1254" },
345 { "Turkish (Mac)",
346 10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
347 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
348 "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
349 { "Latin 3 (ISO)",
350 28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
351 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
352 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
353 "iso-8859-3", "iso-8859-3", "iso-8859-3" },
354 { "Turkish (ISO)",
355 28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
356 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
357 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
358 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
359 "iso-8859-9", "iso-8859-9", "iso-8859-9" }
360 };
361 static const MIME_CP_INFO vietnamese_cp[] =
362 {
363 { "Vietnamese (Windows)",
364 1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
365 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
366 MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
367 MIMECONTF_MIME_LATEST,
368 "windows-1258", "windows-1258", "windows-1258" }
369 };
370
371 static const WCHAR asciiW[] = {'a','s','c','i','i',0};
372
373 static const MIME_CP_INFO western_cp[] =
374 {
375 { "IBM EBCDIC (US-Canada)",
376 37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
377 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
378 "ibm037", "ibm037", "ibm037" },
379 { "OEM United States",
380 437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
381 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
382 "ibm437", "ibm437", "ibm437" },
383 { "IBM EBCDIC (International)",
384 500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
385 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
386 "ibm500", "ibm500", "ibm500" },
387 { "Western European (DOS)",
388 850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
389 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
390 "ibm850", "ibm850", "ibm850" },
391 { "Portuguese (DOS)",
392 860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
393 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
394 "ibm860", "ibm860", "ibm860" },
395 { "Icelandic (DOS)",
396 861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
397 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
398 "ibm861", "ibm861", "ibm861" },
399 { "French Canadian (DOS)",
400 863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
401 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
402 "ibm863", "ibm863", "ibm863" },
403 { "Nordic (DOS)",
404 865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
405 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
406 "ibm865", "ibm865", "ibm865" },
407 { "Western European (Windows)",
408 1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
409 MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
410 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
411 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
412 "windows-1252", "windows-1252", "iso-8859-1" },
413 { "Western European (Mac)",
414 10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
415 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
416 "macintosh", "macintosh", "macintosh" },
417 { "Icelandic (Mac)",
418 10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
419 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
420 "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
421 { "US-ASCII",
422 20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
423 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
424 MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
425 "us-ascii", "us-ascii", "us-ascii", asciiW },
426 { "Western European (ISO)",
427 28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
428 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
429 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
430 MIMECONTF_MIME_LATEST,
431 "iso-8859-1", "iso-8859-1", "iso-8859-1" },
432 { "Latin 9 (ISO)",
433 28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
434 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
435 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
436 MIMECONTF_MIME_LATEST,
437 "iso-8859-15", "iso-8859-15", "iso-8859-15" }
438 };
439 static const MIME_CP_INFO unicode_cp[] =
440 {
441 { "Unicode",
442 CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
443 MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
444 MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
445 MIMECONTF_MIME_LATEST,
446 "unicode", "unicode", "unicode" },
447 { "Unicode (UTF-7)",
448 CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
449 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
450 MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
451 "utf-7", "utf-7", "utf-7" },
452 { "Unicode (UTF-8)",
453 CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
454 MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
455 MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
456 MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
457 "utf-8", "utf-8", "utf-8" }
458 };
459
460 static const struct mlang_data
461 {
462 const char *description;
463 UINT family_codepage;
464 UINT number_of_cp;
465 const MIME_CP_INFO *mime_cp_info;
466 const char *fixed_font;
467 const char *proportional_font;
468 SCRIPT_ID sid;
469 } mlang_data[] =
470 {
471 { "Arabic",1256,sizeof(arabic_cp)/sizeof(arabic_cp[0]),arabic_cp,
472 "Courier","Arial", sidArabic }, /* FIXME */
473 { "Baltic",1257,sizeof(baltic_cp)/sizeof(baltic_cp[0]),baltic_cp,
474 "Courier","Arial", sidAsciiLatin }, /* FIXME */
475 { "Chinese Simplified",936,sizeof(chinese_simplified_cp)/sizeof(chinese_simplified_cp[0]),chinese_simplified_cp,
476 "Courier","Arial", sidHan }, /* FIXME */
477 { "Chinese Traditional",950,sizeof(chinese_traditional_cp)/sizeof(chinese_traditional_cp[0]),chinese_traditional_cp,
478 "Courier","Arial", sidBopomofo }, /* FIXME */
479 { "Central European",1250,sizeof(central_european_cp)/sizeof(central_european_cp[0]),central_european_cp,
480 "Courier","Arial", sidAsciiLatin }, /* FIXME */
481 { "Cyrillic",1251,sizeof(cyrillic_cp)/sizeof(cyrillic_cp[0]),cyrillic_cp,
482 "Courier","Arial", sidCyrillic }, /* FIXME */
483 { "Greek",1253,sizeof(greek_cp)/sizeof(greek_cp[0]),greek_cp,
484 "Courier","Arial", sidGreek }, /* FIXME */
485 { "Hebrew",1255,sizeof(hebrew_cp)/sizeof(hebrew_cp[0]),hebrew_cp,
486 "Courier","Arial", sidHebrew }, /* FIXME */
487 { "Japanese",932,sizeof(japanese_cp)/sizeof(japanese_cp[0]),japanese_cp,
488 "MS Gothic","MS PGothic", sidKana },
489 { "Korean",949,sizeof(korean_cp)/sizeof(korean_cp[0]),korean_cp,
490 "Courier","Arial", sidHangul }, /* FIXME */
491 { "Thai",874,sizeof(thai_cp)/sizeof(thai_cp[0]),thai_cp,
492 "Courier","Arial", sidThai }, /* FIXME */
493 { "Turkish",1254,sizeof(turkish_cp)/sizeof(turkish_cp[0]),turkish_cp,
494 "Courier","Arial", sidAsciiLatin }, /* FIXME */
495 { "Vietnamese",1258,sizeof(vietnamese_cp)/sizeof(vietnamese_cp[0]),vietnamese_cp,
496 "Courier","Arial", sidAsciiLatin }, /* FIXME */
497 { "Western European",1252,sizeof(western_cp)/sizeof(western_cp[0]),western_cp,
498 "Courier","Arial", sidAsciiLatin }, /* FIXME */
499 { "Unicode",CP_UNICODE,sizeof(unicode_cp)/sizeof(unicode_cp[0]),unicode_cp,
500 "Courier","Arial" } /* FIXME */
501 };
502
503 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
504
505 static LONG dll_count;
506
507 /*
508 * Japanese Detection and Conversion Functions
509 */
510
511 #define HANKATA(A) ((A >= 161) && (A <= 223))
512 #define ISEUC(A) ((A >= 161) && (A <= 254))
513 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
514 #define SJIS1(A) (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
515 #define SJIS2(A) ((A >= 64) && (A <= 252))
516 #define ISMARU(A) ((A >= 202) && (A <= 206))
517 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
518
519 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
520 {
521 UINT code = 0;
522 DWORD i = 0;
523 unsigned char c1,c2;
524
525 while ((code == 0 || code == 51932) && i < count)
526 {
527 c1 = input[i];
528 if (c1 == 0x1b /* ESC */)
529 {
530 i++;
531 if (i >= count)
532 return code;
533 c1 = input[i];
534 if (c1 == '$')
535 {
536 i++;
537 if (i >= count)
538 return code;
539 c1 = input[i];
540 if (c1 =='B' || c1 == '@')
541 code = 50220;
542 }
543 if (c1 == 'K')
544 code = 50220;
545 }
546 else if (c1 >= 129)
547 {
548 i++;
549 if (i >= count)
550 return code;
551 c2 = input[i];
552 if NOTEUC(c1,c2)
553 code = 932;
554 else if (ISEUC(c1) && ISEUC(c2))
555 code = 51932;
556 else if (((c1 == 142)) && HANKATA(c2))
557 code = 51932;
558 }
559 i++;
560 }
561 return code;
562 }
563
564 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
565 {
566 unsigned char c1 = *p1;
567 unsigned char c2 = *p2;
568 int row = c1 < 95 ? 112 : 176;
569 int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
570
571 *p1 = ((c1 + 1) >> 1) + row;
572 *p2 = c2 + cell;
573 }
574
575 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
576 {
577 unsigned char c1 = *p1;
578 unsigned char c2 = *p2;
579 int shift = c2 < 159;
580 int row = c1 < 160 ? 112 : 176;
581 int cell = shift ? (31 + (c2 > 127)): 126;
582
583 *p1 = ((c1 - row) << 1) - shift;
584 *p2 -= cell;
585 }
586
587 static int han2zen(unsigned char *p1, unsigned char *p2)
588 {
589 BOOL maru = FALSE;
590 BOOL nigori = FALSE;
591 static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
592 131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
593 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
594 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
595 131,129,129 };
596 static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
597 72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
598 96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
599 129,130,132,134,136,137,138,139,140,141,143,147,74,75};
600
601 if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
602 nigori = TRUE;
603 else if ((*p2 == 223) && (ISMARU(*p1)))
604 maru = TRUE;
605
606 if (*p1 >= 161 && *p1 <= 223)
607 {
608 unsigned char index = *p1 - 161;
609 *p1 = char1[index];
610 *p2 = char2[index];
611 }
612
613 if (maru || nigori)
614 {
615 if (nigori)
616 {
617 if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
618 (*p2)++;
619 else if ((*p1 == 131) && (*p2 == 69))
620 *p2 = 148;
621 }
622 else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
623 *p2+= 2;
624
625 return 1;
626 }
627
628 return 0;
629 }
630
631
632 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
633 {
634 DWORD i = 0;
635 int j = 0;
636 unsigned char p2,p;
637 BOOL shifted = FALSE;
638
639 while (i < count)
640 {
641 p = input[i];
642 if (p == 0x1b /* ESC */)
643 {
644 i++;
645 if (i >= count)
646 return 0;
647 p2 = input[i];
648 if (p2 == '$' || p2 =='(')
649 i++;
650 if (p2 == 'K' || p2 =='$')
651 shifted = TRUE;
652 else
653 shifted = FALSE;
654 }
655 else
656 {
657 if (shifted)
658 {
659 i++;
660 if (i >= count)
661 return 0;
662 p2 = input[i];
663 jis2sjis(&p,&p2);
664 output[j++]=p;
665 output[j++]=p2;
666 }
667 else
668 {
669 output[j++] = p;
670 }
671 }
672 i++;
673 }
674 return j;
675 }
676
677 static inline int exit_shift(LPSTR out, int c)
678 {
679 if (out)
680 {
681 out[c] = 0x1b;
682 out[c+1] = '(';
683 out[c+2] = 'B';
684 }
685 return 3;
686 }
687
688 static inline int enter_shift(LPSTR out, int c)
689 {
690 if (out)
691 {
692 out[c] = 0x1b;
693 out[c+1] = '$';
694 out[c+2] = 'B';
695 }
696 return 3;
697 }
698
699
700 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
701 {
702 DWORD i = 0;
703 int j = 0;
704 unsigned char p2,p;
705 BOOL shifted = FALSE;
706
707 while (i < count)
708 {
709 p = input[i] & 0xff;
710 if (p == 10 || p == 13) /* NL and CR */
711 {
712 if (shifted)
713 {
714 shifted = FALSE;
715 j += exit_shift(output,j);
716 }
717 if (output)
718 output[j++] = p;
719 else
720 j++;
721 }
722 else
723 {
724 if (SJIS1(p))
725 {
726 i++;
727 if (i >= count)
728 return 0;
729 p2 = input[i] & 0xff;
730 if (SJIS2(p2))
731 {
732 sjis2jis(&p,&p2);
733 if (!shifted)
734 {
735 shifted = TRUE;
736 j+=enter_shift(output,j);
737 }
738 }
739
740 if (output)
741 {
742 output[j++]=p;
743 output[j++]=p2;
744 }
745 else
746 j+=2;
747 }
748 else
749 {
750 if (HANKATA(p))
751 {
752 if ((i+1) >= count)
753 return 0;
754 p2 = input[i+1] & 0xff;
755 i+=han2zen(&p,&p2);
756 sjis2jis(&p,&p2);
757 if (!shifted)
758 {
759 shifted = TRUE;
760 j+=enter_shift(output,j);
761 }
762 if (output)
763 {
764 output[j++]=p;
765 output[j++]=p2;
766 }
767 else
768 j+=2;
769 }
770 else
771 {
772 if (shifted)
773 {
774 shifted = FALSE;
775 j += exit_shift(output,j);
776 }
777 if (output)
778 output[j++]=p;
779 else
780 j++;
781 }
782 }
783 }
784 i++;
785 }
786 if (shifted)
787 j += exit_shift(output,j);
788 return j;
789 }
790
791 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
792 LPWSTR output, DWORD out_count)
793 {
794 CHAR *sjis_string;
795 UINT rc = 0;
796 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
797 rc = ConvertJIS2SJIS(input,count,sjis_string);
798 if (rc)
799 {
800 TRACE("%s\n",debugstr_an(sjis_string,rc));
801 if (output)
802 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
803 else
804 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
805 }
806 HeapFree(GetProcessHeap(),0,sjis_string);
807 return rc;
808
809 }
810
811 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
812 LPWSTR output, DWORD out_count)
813 {
814 CHAR *sjis_string;
815 UINT rc = 0;
816 int code = DetectJapaneseCode(input,count);
817 TRACE("Japanese code %i\n",code);
818
819 switch (code)
820 {
821 case 0:
822 if (output)
823 rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
824 else
825 rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
826 break;
827
828 case 932:
829 if (output)
830 rc = MultiByteToWideChar(932,0,input,count,output,out_count);
831 else
832 rc = MultiByteToWideChar(932,0,input,count,0,0);
833 break;
834
835 case 51932:
836 if (output)
837 rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
838 else
839 rc = MultiByteToWideChar(20932,0,input,count,0,0);
840 break;
841
842 case 50220:
843 sjis_string = HeapAlloc(GetProcessHeap(),0,count);
844 rc = ConvertJIS2SJIS(input,count,sjis_string);
845 if (rc)
846 {
847 TRACE("%s\n",debugstr_an(sjis_string,rc));
848 if (output)
849 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
850 else
851 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
852 }
853 HeapFree(GetProcessHeap(),0,sjis_string);
854 break;
855 }
856 return rc;
857 }
858
859 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
860 LPSTR output, DWORD out_count)
861 {
862 CHAR *sjis_string;
863 INT len;
864 UINT rc = 0;
865
866 len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
867 sjis_string = HeapAlloc(GetProcessHeap(),0,len);
868 WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
869 TRACE("%s\n",debugstr_an(sjis_string,len));
870
871 rc = ConvertSJIS2JIS(sjis_string, len, NULL);
872 if (out_count >= rc)
873 {
874 ConvertSJIS2JIS(sjis_string, len, output);
875 }
876 HeapFree(GetProcessHeap(),0,sjis_string);
877 return rc;
878
879 }
880
881 /*
882 * Dll lifetime tracking declaration
883 */
884 static void LockModule(void)
885 {
886 InterlockedIncrement(&dll_count);
887 }
888
889 static void UnlockModule(void)
890 {
891 InterlockedDecrement(&dll_count);
892 }
893
894 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
895 {
896 switch(fdwReason) {
897 case DLL_PROCESS_ATTACH:
898 instance = hInstDLL;
899 MLANG_tls_index = TlsAlloc();
900 DisableThreadLibraryCalls(hInstDLL);
901 break;
902 case DLL_PROCESS_DETACH:
903 if (lpv) break;
904 TlsFree(MLANG_tls_index);
905 break;
906 }
907 return TRUE;
908 }
909
910 HRESULT WINAPI ConvertINetMultiByteToUnicode(
911 LPDWORD pdwMode,
912 DWORD dwEncoding,
913 LPCSTR pSrcStr,
914 LPINT pcSrcSize,
915 LPWSTR pDstStr,
916 LPINT pcDstSize)
917 {
918 INT src_len = -1;
919
920 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
921 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
922
923 if (!pcDstSize)
924 return E_FAIL;
925
926 if (!pcSrcSize)
927 pcSrcSize = &src_len;
928
929 if (!*pcSrcSize)
930 {
931 *pcDstSize = 0;
932 return S_OK;
933 }
934
935 /* forwarding euc-jp to EUC-JP */
936 if (dwEncoding == 51932)
937 dwEncoding = 20932;
938
939 switch (dwEncoding)
940 {
941 case CP_UNICODE:
942 if (*pcSrcSize == -1)
943 *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
944 *pcDstSize = min(*pcSrcSize, *pcDstSize);
945 *pcSrcSize *= sizeof(WCHAR);
946 if (pDstStr)
947 memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
948 break;
949
950 case 50220:
951 case 50221:
952 case 50222:
953 *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
954 break;
955 case 50932:
956 *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
957 break;
958
959 default:
960 if (*pcSrcSize == -1)
961 *pcSrcSize = lstrlenA(pSrcStr);
962
963 if (pDstStr)
964 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
965 else
966 *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
967 break;
968 }
969
970 if (!*pcDstSize)
971 return E_FAIL;
972
973 return S_OK;
974 }
975
976 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
977 LPDWORD pdwMode,
978 DWORD dwEncoding,
979 LPCWSTR pSrcStr,
980 LPINT pcSrcSize,
981 LPSTR pDstStr,
982 LPINT pcDstSize)
983 {
984 INT destsz, size;
985 INT src_len = -1;
986
987 TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
988 debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
989
990 if (!pcDstSize)
991 return S_OK;
992
993 if (!pcSrcSize)
994 pcSrcSize = &src_len;
995
996 destsz = (pDstStr) ? *pcDstSize : 0;
997 *pcDstSize = 0;
998
999 if (!pSrcStr || !*pcSrcSize)
1000 return S_OK;
1001
1002 if (*pcSrcSize == -1)
1003 *pcSrcSize = lstrlenW(pSrcStr);
1004
1005 /* forwarding euc-jp to EUC-JP */
1006 if (dwEncoding == 51932)
1007 dwEncoding = 20932;
1008
1009 if (dwEncoding == CP_UNICODE)
1010 {
1011 if (*pcSrcSize == -1)
1012 *pcSrcSize = lstrlenW(pSrcStr);
1013
1014 size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
1015 if (pDstStr)
1016 memmove(pDstStr, pSrcStr, size);
1017
1018 if (size >= destsz)
1019 goto fail;
1020 }
1021 else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
1022 {
1023 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
1024 if (!size)
1025 goto fail;
1026
1027 if (pDstStr)
1028 {
1029 size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
1030 destsz);
1031 if (!size)
1032 goto fail;
1033 }
1034
1035 }
1036 else
1037 {
1038 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1039 NULL, 0, NULL, NULL);
1040 if (!size)
1041 goto fail;
1042
1043 if (pDstStr)
1044 {
1045 size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
1046 pDstStr, destsz, NULL, NULL);
1047 if (!size)
1048 goto fail;
1049 }
1050 }
1051
1052 *pcDstSize = size;
1053 return S_OK;
1054
1055 fail:
1056 *pcSrcSize = 0;
1057 *pcDstSize = 0;
1058 return E_FAIL;
1059 }
1060
1061 HRESULT WINAPI ConvertINetString(
1062 LPDWORD pdwMode,
1063 DWORD dwSrcEncoding,
1064 DWORD dwDstEncoding,
1065 LPCSTR pSrcStr,
1066 LPINT pcSrcSize,
1067 LPSTR pDstStr,
1068 LPINT pcDstSize
1069 )
1070 {
1071 TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
1072 debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
1073
1074 if (dwSrcEncoding == CP_UNICODE)
1075 {
1076 INT cSrcSizeW;
1077 if (pcSrcSize && *pcSrcSize != -1)
1078 {
1079 cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
1080 pcSrcSize = &cSrcSizeW;
1081 }
1082 return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
1083 }
1084 else if (dwDstEncoding == CP_UNICODE)
1085 {
1086 HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
1087 *pcDstSize *= sizeof(WCHAR);
1088 return hr;
1089 }
1090 else
1091 {
1092 INT cDstSizeW;
1093 LPWSTR pDstStrW;
1094 HRESULT hr;
1095
1096 TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
1097
1098 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
1099 if (hr != S_OK)
1100 return hr;
1101
1102 pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
1103 hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
1104 if (hr == S_OK)
1105 hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
1106
1107 HeapFree(GetProcessHeap(), 0, pDstStrW);
1108 return hr;
1109 }
1110 }
1111
1112 static HRESULT GetFamilyCodePage(
1113 UINT uiCodePage,
1114 UINT* puiFamilyCodePage)
1115 {
1116 UINT i, n;
1117
1118 TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
1119
1120 if (!puiFamilyCodePage) return S_FALSE;
1121
1122 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1123 {
1124 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1125 {
1126 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1127 {
1128 *puiFamilyCodePage = mlang_data[i].family_codepage;
1129 return S_OK;
1130 }
1131 }
1132 }
1133
1134 return S_FALSE;
1135 }
1136
1137 HRESULT WINAPI IsConvertINetStringAvailable(
1138 DWORD dwSrcEncoding,
1139 DWORD dwDstEncoding)
1140 {
1141 UINT src_family, dst_family;
1142
1143 TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
1144
1145 if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
1146 GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
1147 return S_FALSE;
1148
1149 if (src_family == dst_family) return S_OK;
1150
1151 /* we can convert any codepage to/from unicode */
1152 if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
1153
1154 return S_FALSE;
1155 }
1156
1157 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
1158 {
1159 CHAR buffer[MAX_RFC1766_NAME];
1160 INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1161 INT i;
1162
1163 if (n)
1164 {
1165 i = PRIMARYLANGID(lcid);
1166 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1167 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1168 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1169
1170 buffer[n - 1] = '-';
1171 i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1172 if (!i)
1173 buffer[n - 1] = '\0';
1174 }
1175 else
1176 i = 0;
1177
1178 LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
1179 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1180 }
1181 return E_FAIL;
1182 }
1183
1184 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
1185 {
1186 WCHAR buffer[MAX_RFC1766_NAME];
1187 INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
1188 INT i;
1189
1190 if (n)
1191 {
1192 i = PRIMARYLANGID(lcid);
1193 if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
1194 (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
1195 (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
1196
1197 buffer[n - 1] = '-';
1198 i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
1199 if (!i)
1200 buffer[n - 1] = '\0';
1201 }
1202 else
1203 i = 0;
1204
1205 LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
1206 return ((n + i) > len) ? E_INVALIDARG : S_OK;
1207 }
1208 return E_FAIL;
1209 }
1210
1211 HRESULT WINAPI LcidToRfc1766A(
1212 LCID lcid,
1213 LPSTR pszRfc1766,
1214 INT nChar)
1215 {
1216 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1217 if (!pszRfc1766)
1218 return E_INVALIDARG;
1219
1220 return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
1221 }
1222
1223 HRESULT WINAPI LcidToRfc1766W(
1224 LCID lcid,
1225 LPWSTR pszRfc1766,
1226 INT nChar)
1227 {
1228 TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
1229 if (!pszRfc1766)
1230 return E_INVALIDARG;
1231
1232 return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
1233 }
1234
1235 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
1236 {
1237 RFC1766INFO info;
1238 ULONG num;
1239
1240 while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
1241 {
1242 if (!strcmpiW(info.wszRfc1766, rfc1766))
1243 {
1244 *lcid = info.lcid;
1245 return S_OK;
1246 }
1247 if (strlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
1248 {
1249 *lcid = PRIMARYLANGID(info.lcid);
1250 return S_OK;
1251 }
1252 }
1253
1254 return E_FAIL;
1255 }
1256
1257 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
1258 {
1259 IEnumRfc1766 *enumrfc1766;
1260 HRESULT hr;
1261
1262 TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
1263
1264 if (!pLocale || !pszRfc1766)
1265 return E_INVALIDARG;
1266
1267 hr = EnumRfc1766_create(0, &enumrfc1766);
1268 if (FAILED(hr))
1269 return hr;
1270
1271 hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
1272 IEnumRfc1766_Release(enumrfc1766);
1273
1274 return hr;
1275 }
1276
1277 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
1278 {
1279 WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
1280
1281 if (!rfc1766A)
1282 return E_INVALIDARG;
1283
1284 MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
1285 rfc1766W[MAX_RFC1766_NAME] = 0;
1286
1287 return Rfc1766ToLcidW(lcid, rfc1766W);
1288 }
1289
1290 /******************************************************************************
1291 * MLANG ClassFactory
1292 */
1293 typedef struct {
1294 IClassFactory IClassFactory_iface;
1295 LONG ref;
1296 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1297 } IClassFactoryImpl;
1298
1299 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1300 {
1301 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
1302 }
1303
1304 struct object_creation_info
1305 {
1306 const CLSID *clsid;
1307 LPCSTR szClassName;
1308 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
1309 };
1310
1311 static const struct object_creation_info object_creation[] =
1312 {
1313 { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
1314 { &CLSID_CMLangConvertCharset, "CLSID_CMLangConvertCharset", MLangConvertCharset_create }
1315 };
1316
1317 static HRESULT WINAPI MLANGCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1318 {
1319 TRACE("%s\n", debugstr_guid(riid) );
1320
1321 if (IsEqualGUID(riid, &IID_IUnknown)
1322 || IsEqualGUID(riid, &IID_IClassFactory))
1323 {
1324 IClassFactory_AddRef(iface);
1325 *ppobj = iface;
1326 return S_OK;
1327 }
1328
1329 *ppobj = NULL;
1330 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
1331 return E_NOINTERFACE;
1332 }
1333
1334 static ULONG WINAPI MLANGCF_AddRef(IClassFactory *iface)
1335 {
1336 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1337 return InterlockedIncrement(&This->ref);
1338 }
1339
1340 static ULONG WINAPI MLANGCF_Release(IClassFactory *iface)
1341 {
1342 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1343 ULONG ref = InterlockedDecrement(&This->ref);
1344
1345 if (ref == 0)
1346 {
1347 TRACE("Destroying %p\n", This);
1348 HeapFree(GetProcessHeap(), 0, This);
1349 }
1350
1351 return ref;
1352 }
1353
1354 static HRESULT WINAPI MLANGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1355 REFIID riid, void **ppobj)
1356 {
1357 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
1358 HRESULT hres;
1359 LPUNKNOWN punk;
1360
1361 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1362
1363 *ppobj = NULL;
1364 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
1365 if (SUCCEEDED(hres)) {
1366 hres = IUnknown_QueryInterface(punk, riid, ppobj);
1367 IUnknown_Release(punk);
1368 }
1369 TRACE("returning (%p) -> %x\n", *ppobj, hres);
1370 return hres;
1371 }
1372
1373 static HRESULT WINAPI MLANGCF_LockServer(IClassFactory *iface, BOOL dolock)
1374 {
1375 if (dolock)
1376 LockModule();
1377 else
1378 UnlockModule();
1379
1380 return S_OK;
1381 }
1382
1383 static const IClassFactoryVtbl MLANGCF_Vtbl =
1384 {
1385 MLANGCF_QueryInterface,
1386 MLANGCF_AddRef,
1387 MLANGCF_Release,
1388 MLANGCF_CreateInstance,
1389 MLANGCF_LockServer
1390 };
1391
1392 /******************************************************************
1393 * DllGetClassObject (MLANG.@)
1394 */
1395 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
1396 {
1397 unsigned int i;
1398 IClassFactoryImpl *factory;
1399
1400 TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
1401
1402 if ( !IsEqualGUID( &IID_IClassFactory, iid )
1403 && ! IsEqualGUID( &IID_IUnknown, iid) )
1404 return E_NOINTERFACE;
1405
1406 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
1407 {
1408 if (IsEqualGUID(object_creation[i].clsid, rclsid))
1409 break;
1410 }
1411
1412 if (i == sizeof(object_creation)/sizeof(object_creation[0]))
1413 {
1414 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
1415 return CLASS_E_CLASSNOTAVAILABLE;
1416 }
1417
1418 TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
1419
1420 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
1421 if (factory == NULL) return E_OUTOFMEMORY;
1422
1423 factory->IClassFactory_iface.lpVtbl = &MLANGCF_Vtbl;
1424 factory->ref = 1;
1425
1426 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
1427
1428 *ppv = &factory->IClassFactory_iface;
1429
1430 TRACE("(%p) <- %p\n", ppv, &factory->IClassFactory_iface);
1431
1432 return S_OK;
1433 }
1434
1435
1436 /******************************************************************************/
1437
1438 typedef struct tagMLang_impl
1439 {
1440 IMLangFontLink IMLangFontLink_iface;
1441 IMultiLanguage IMultiLanguage_iface;
1442 IMultiLanguage3 IMultiLanguage3_iface;
1443 IMLangFontLink2 IMLangFontLink2_iface;
1444 IMLangLineBreakConsole IMLangLineBreakConsole_iface;
1445 LONG ref;
1446 DWORD total_cp, total_scripts;
1447 } MLang_impl;
1448
1449 /******************************************************************************/
1450
1451 typedef struct tagEnumCodePage_impl
1452 {
1453 IEnumCodePage IEnumCodePage_iface;
1454 LONG ref;
1455 MIMECPINFO *cpinfo;
1456 DWORD total, pos;
1457 } EnumCodePage_impl;
1458
1459 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
1460 {
1461 return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
1462 }
1463
1464 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
1465 IEnumCodePage* iface,
1466 REFIID riid,
1467 void** ppvObject)
1468 {
1469 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1470
1471 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1472
1473 if (IsEqualGUID(riid, &IID_IUnknown)
1474 || IsEqualGUID(riid, &IID_IEnumCodePage))
1475 {
1476 IEnumCodePage_AddRef(iface);
1477 TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
1478 *ppvObject = &This->IEnumCodePage_iface;
1479 return S_OK;
1480 }
1481
1482 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1483 return E_NOINTERFACE;
1484 }
1485
1486 static ULONG WINAPI fnIEnumCodePage_AddRef(
1487 IEnumCodePage* iface)
1488 {
1489 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1490 return InterlockedIncrement(&This->ref);
1491 }
1492
1493 static ULONG WINAPI fnIEnumCodePage_Release(
1494 IEnumCodePage* iface)
1495 {
1496 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1497 ULONG ref = InterlockedDecrement(&This->ref);
1498
1499 TRACE("%p ref = %d\n", This, ref);
1500 if (ref == 0)
1501 {
1502 TRACE("Destroying %p\n", This);
1503 HeapFree(GetProcessHeap(), 0, This->cpinfo);
1504 HeapFree(GetProcessHeap(), 0, This);
1505 }
1506
1507 return ref;
1508 }
1509
1510 static HRESULT WINAPI fnIEnumCodePage_Clone(
1511 IEnumCodePage* iface,
1512 IEnumCodePage** ppEnum)
1513 {
1514 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1515 FIXME("%p %p\n", This, ppEnum);
1516 return E_NOTIMPL;
1517 }
1518
1519 static HRESULT WINAPI fnIEnumCodePage_Next(
1520 IEnumCodePage* iface,
1521 ULONG celt,
1522 PMIMECPINFO rgelt,
1523 ULONG* pceltFetched)
1524 {
1525 ULONG i;
1526 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1527
1528 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1529
1530 if (!pceltFetched) return S_FALSE;
1531 *pceltFetched = 0;
1532
1533 if (!rgelt) return S_FALSE;
1534
1535 if (This->pos + celt > This->total)
1536 celt = This->total - This->pos;
1537
1538 if (!celt) return S_FALSE;
1539
1540 memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
1541 *pceltFetched = celt;
1542 This->pos += celt;
1543
1544 for (i = 0; i < celt; i++)
1545 {
1546 TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
1547 i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
1548 rgelt[i].uiFamilyCodePage,
1549 wine_dbgstr_w(rgelt[i].wszDescription),
1550 wine_dbgstr_w(rgelt[i].wszWebCharset),
1551 wine_dbgstr_w(rgelt[i].wszHeaderCharset),
1552 wine_dbgstr_w(rgelt[i].wszBodyCharset),
1553 wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
1554 wine_dbgstr_w(rgelt[i].wszProportionalFont),
1555 rgelt[i].bGDICharset);
1556 }
1557 return S_OK;
1558 }
1559
1560 static HRESULT WINAPI fnIEnumCodePage_Reset(
1561 IEnumCodePage* iface)
1562 {
1563 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1564
1565 TRACE("%p\n", This);
1566
1567 This->pos = 0;
1568 return S_OK;
1569 }
1570
1571 static HRESULT WINAPI fnIEnumCodePage_Skip(
1572 IEnumCodePage* iface,
1573 ULONG celt)
1574 {
1575 EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
1576
1577 TRACE("%p %u\n", This, celt);
1578
1579 if (celt >= This->total) return S_FALSE;
1580
1581 This->pos += celt;
1582 return S_OK;
1583 }
1584
1585 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
1586 {
1587 fnIEnumCodePage_QueryInterface,
1588 fnIEnumCodePage_AddRef,
1589 fnIEnumCodePage_Release,
1590 fnIEnumCodePage_Clone,
1591 fnIEnumCodePage_Next,
1592 fnIEnumCodePage_Reset,
1593 fnIEnumCodePage_Skip
1594 };
1595
1596 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
1597 LANGID LangId, IEnumCodePage** ppEnumCodePage )
1598 {
1599 EnumCodePage_impl *ecp;
1600 MIMECPINFO *cpinfo;
1601 UINT i, n;
1602
1603 TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
1604
1605 if (!grfFlags) /* enumerate internal data base of encodings */
1606 grfFlags = MIMECONTF_MIME_LATEST;
1607
1608 ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
1609 ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
1610 ecp->ref = 1;
1611 ecp->pos = 0;
1612 ecp->total = 0;
1613 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1614 {
1615 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1616 {
1617 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1618 ecp->total++;
1619 }
1620 }
1621
1622 ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
1623 sizeof(MIMECPINFO) * ecp->total);
1624 cpinfo = ecp->cpinfo;
1625
1626 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1627 {
1628 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1629 {
1630 if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
1631 fill_cp_info(&mlang_data[i], n, cpinfo++);
1632 }
1633 }
1634
1635 TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
1636
1637 *ppEnumCodePage = &ecp->IEnumCodePage_iface;
1638
1639 return S_OK;
1640 }
1641
1642 /******************************************************************************/
1643
1644 typedef struct tagEnumScript_impl
1645 {
1646 IEnumScript IEnumScript_iface;
1647 LONG ref;
1648 SCRIPTINFO *script_info;
1649 DWORD total, pos;
1650 } EnumScript_impl;
1651
1652 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
1653 {
1654 return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
1655 }
1656
1657 static HRESULT WINAPI fnIEnumScript_QueryInterface(
1658 IEnumScript* iface,
1659 REFIID riid,
1660 void** ppvObject)
1661 {
1662 EnumScript_impl *This = impl_from_IEnumScript( iface );
1663
1664 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
1665
1666 if (IsEqualGUID(riid, &IID_IUnknown)
1667 || IsEqualGUID(riid, &IID_IEnumScript))
1668 {
1669 IEnumScript_AddRef(iface);
1670 TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
1671 *ppvObject = &This->IEnumScript_iface;
1672 return S_OK;
1673 }
1674
1675 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1676 return E_NOINTERFACE;
1677 }
1678
1679 static ULONG WINAPI fnIEnumScript_AddRef(
1680 IEnumScript* iface)
1681 {
1682 EnumScript_impl *This = impl_from_IEnumScript( iface );
1683 return InterlockedIncrement(&This->ref);
1684 }
1685
1686 static ULONG WINAPI fnIEnumScript_Release(
1687 IEnumScript* iface)
1688 {
1689 EnumScript_impl *This = impl_from_IEnumScript( iface );
1690 ULONG ref = InterlockedDecrement(&This->ref);
1691
1692 TRACE("%p ref = %d\n", This, ref);
1693 if (ref == 0)
1694 {
1695 TRACE("Destroying %p\n", This);
1696 HeapFree(GetProcessHeap(), 0, This->script_info);
1697 HeapFree(GetProcessHeap(), 0, This);
1698 }
1699
1700 return ref;
1701 }
1702
1703 static HRESULT WINAPI fnIEnumScript_Clone(
1704 IEnumScript* iface,
1705 IEnumScript** ppEnum)
1706 {
1707 EnumScript_impl *This = impl_from_IEnumScript( iface );
1708 FIXME("%p %p: stub!\n", This, ppEnum);
1709 return E_NOTIMPL;
1710 }
1711
1712 static HRESULT WINAPI fnIEnumScript_Next(
1713 IEnumScript* iface,
1714 ULONG celt,
1715 PSCRIPTINFO rgelt,
1716 ULONG* pceltFetched)
1717 {
1718 EnumScript_impl *This = impl_from_IEnumScript( iface );
1719
1720 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
1721
1722 if (!pceltFetched || !rgelt) return E_FAIL;
1723
1724 *pceltFetched = 0;
1725
1726 if (This->pos + celt > This->total)
1727 celt = This->total - This->pos;
1728
1729 if (!celt) return S_FALSE;
1730
1731 memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
1732 *pceltFetched = celt;
1733 This->pos += celt;
1734
1735 return S_OK;
1736 }
1737
1738 static HRESULT WINAPI fnIEnumScript_Reset(
1739 IEnumScript* iface)
1740 {
1741 EnumScript_impl *This = impl_from_IEnumScript( iface );
1742
1743 TRACE("%p\n", This);
1744
1745 This->pos = 0;
1746 return S_OK;
1747 }
1748
1749 static HRESULT WINAPI fnIEnumScript_Skip(
1750 IEnumScript* iface,
1751 ULONG celt)
1752 {
1753 EnumScript_impl *This = impl_from_IEnumScript( iface );
1754
1755 TRACE("%p %u\n", This, celt);
1756
1757 if (celt >= This->total) return S_FALSE;
1758
1759 This->pos += celt;
1760 return S_OK;
1761 }
1762
1763 static const IEnumScriptVtbl IEnumScript_vtbl =
1764 {
1765 fnIEnumScript_QueryInterface,
1766 fnIEnumScript_AddRef,
1767 fnIEnumScript_Release,
1768 fnIEnumScript_Clone,
1769 fnIEnumScript_Next,
1770 fnIEnumScript_Reset,
1771 fnIEnumScript_Skip
1772 };
1773
1774 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
1775 LANGID LangId, IEnumScript** ppEnumScript )
1776 {
1777 EnumScript_impl *es;
1778 UINT i;
1779
1780 TRACE("%p, %08x, %04x, %p\n", mlang, dwFlags, LangId, ppEnumScript);
1781
1782 if (!dwFlags) /* enumerate all available scripts */
1783 dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
1784
1785 es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
1786 es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
1787 es->ref = 1;
1788 es->pos = 0;
1789 /* do not enumerate unicode flavours */
1790 es->total = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
1791 es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
1792
1793 for (i = 0; i < es->total; i++)
1794 {
1795 es->script_info[i].ScriptId = i;
1796 es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
1797 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
1798 es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
1799 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
1800 es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
1801 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
1802 es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
1803 }
1804
1805 TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
1806
1807 *ppEnumScript = &es->IEnumScript_iface;
1808
1809 return S_OK;
1810 }
1811
1812 /******************************************************************************/
1813
1814 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
1815 {
1816 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
1817 }
1818
1819 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
1820 IMLangFontLink* iface,
1821 REFIID riid,
1822 void** ppvObject)
1823 {
1824 MLang_impl *This = impl_from_IMLangFontLink( iface );
1825 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
1826 }
1827
1828 static ULONG WINAPI fnIMLangFontLink_AddRef(
1829 IMLangFontLink* iface)
1830 {
1831 MLang_impl *This = impl_from_IMLangFontLink( iface );
1832 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
1833 }
1834
1835 static ULONG WINAPI fnIMLangFontLink_Release(
1836 IMLangFontLink* iface)
1837 {
1838 MLang_impl *This = impl_from_IMLangFontLink( iface );
1839 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
1840 }
1841
1842 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
1843 IMLangFontLink* iface,
1844 WCHAR ch_src,
1845 DWORD* codepages)
1846 {
1847 MLang_impl *This = impl_from_IMLangFontLink( iface );
1848 return IMLangFontLink2_GetCharCodePages(&This->IMLangFontLink2_iface, ch_src, codepages);
1849 }
1850
1851 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
1852 IMLangFontLink* iface,
1853 const WCHAR* src,
1854 LONG src_len,
1855 DWORD priority_cp,
1856 DWORD* codepages,
1857 LONG* ret_len)
1858 {
1859 MLang_impl *This = impl_from_IMLangFontLink( iface );
1860 return IMLangFontLink2_GetStrCodePages(&This->IMLangFontLink2_iface, src, src_len, priority_cp,
1861 codepages, ret_len);
1862 }
1863
1864 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
1865 IMLangFontLink* iface,
1866 UINT codepage,
1867 DWORD* codepages)
1868 {
1869 MLang_impl *This = impl_from_IMLangFontLink( iface );
1870 return IMLangFontLink2_CodePageToCodePages(&This->IMLangFontLink2_iface, codepage, codepages);
1871 }
1872
1873 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
1874 IMLangFontLink* iface,
1875 DWORD codepages,
1876 UINT def_codepage,
1877 UINT* codepage)
1878 {
1879 MLang_impl *This = impl_from_IMLangFontLink(iface);
1880 return IMLangFontLink2_CodePagesToCodePage(&This->IMLangFontLink2_iface, codepages,
1881 def_codepage, codepage);
1882 }
1883
1884 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
1885 IMLangFontLink* iface,
1886 HDC hdc,
1887 HFONT hfont,
1888 DWORD* codepages)
1889 {
1890 MLang_impl *This = impl_from_IMLangFontLink(iface);
1891 return IMLangFontLink2_GetFontCodePages(&This->IMLangFontLink2_iface, hdc, hfont, codepages);
1892 }
1893
1894 static HRESULT WINAPI fnIMLangFontLink_MapFont(
1895 IMLangFontLink* iface,
1896 HDC hDC,
1897 DWORD dwCodePages,
1898 HFONT hSrcFont,
1899 HFONT* phDestFont)
1900 {
1901 FIXME("\n");
1902 return E_NOTIMPL;
1903 }
1904
1905 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
1906 IMLangFontLink* iface,
1907 HFONT hFont)
1908 {
1909 FIXME("\n");
1910 return E_NOTIMPL;
1911 }
1912
1913 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
1914 IMLangFontLink* iface)
1915 {
1916 FIXME("\n");
1917 return E_NOTIMPL;
1918 }
1919
1920
1921 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
1922 {
1923 fnIMLangFontLink_QueryInterface,
1924 fnIMLangFontLink_AddRef,
1925 fnIMLangFontLink_Release,
1926 fnIMLangFontLink_GetCharCodePages,
1927 fnIMLangFontLink_GetStrCodePages,
1928 fnIMLangFontLink_CodePageToCodePages,
1929 fnIMLangFontLink_CodePagesToCodePage,
1930 fnIMLangFontLink_GetFontCodePages,
1931 fnIMLangFontLink_MapFont,
1932 fnIMLangFontLink_ReleaseFont,
1933 fnIMLangFontLink_ResetFontMapping,
1934 };
1935
1936 /******************************************************************************/
1937
1938 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
1939 {
1940 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
1941 }
1942
1943 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
1944 IMultiLanguage* iface,
1945 REFIID riid,
1946 void** obj)
1947 {
1948 MLang_impl *This = impl_from_IMultiLanguage( iface );
1949 return IMultiLanguage3_QueryInterface(&This->IMultiLanguage3_iface, riid, obj);
1950 }
1951
1952 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
1953 {
1954 MLang_impl *This = impl_from_IMultiLanguage( iface );
1955 return IMultiLanguage3_AddRef(&This->IMultiLanguage3_iface);
1956 }
1957
1958 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
1959 {
1960 MLang_impl *This = impl_from_IMultiLanguage( iface );
1961 return IMultiLanguage3_Release(&This->IMultiLanguage3_iface);
1962 }
1963
1964 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
1965 IMultiLanguage* iface,
1966 UINT* cp)
1967 {
1968 MLang_impl *This = impl_from_IMultiLanguage( iface );
1969 TRACE("(%p, %p)\n", This, cp);
1970 return IMultiLanguage3_GetNumberOfCodePageInfo(&This->IMultiLanguage3_iface, cp);
1971 }
1972
1973 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
1974 IMultiLanguage* iface,
1975 UINT uiCodePage,
1976 PMIMECPINFO pCodePageInfo)
1977 {
1978 UINT i, n;
1979 MLang_impl *This = impl_from_IMultiLanguage( iface );
1980
1981 TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
1982
1983 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
1984 {
1985 for (n = 0; n < mlang_data[i].number_of_cp; n++)
1986 {
1987 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
1988 {
1989 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
1990 return S_OK;
1991 }
1992 }
1993 }
1994
1995 return S_FALSE;
1996 }
1997
1998 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
1999 IMultiLanguage* iface,
2000 UINT cp,
2001 UINT* family_cp)
2002 {
2003 MLang_impl *This = impl_from_IMultiLanguage( iface );
2004 return IMultiLanguage3_GetFamilyCodePage(&This->IMultiLanguage3_iface, cp, family_cp);
2005 }
2006
2007 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
2008 IMultiLanguage* iface,
2009 DWORD grfFlags,
2010 IEnumCodePage** ppEnumCodePage)
2011 {
2012 MLang_impl *This = impl_from_IMultiLanguage( iface );
2013
2014 TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
2015
2016 return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
2017 }
2018
2019 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
2020 IMultiLanguage* iface,
2021 BSTR Charset,
2022 PMIMECSETINFO pCharsetInfo)
2023 {
2024 MLang_impl *This = impl_from_IMultiLanguage( iface );
2025 return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
2026 }
2027
2028 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
2029 IMultiLanguage* iface,
2030 DWORD src_enc,
2031 DWORD dst_enc)
2032 {
2033 MLang_impl *This = impl_from_IMultiLanguage( iface );
2034 return IMultiLanguage3_IsConvertible(&This->IMultiLanguage3_iface, src_enc, dst_enc);
2035 }
2036
2037 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
2038 IMultiLanguage* iface,
2039 DWORD* mode,
2040 DWORD src_enc,
2041 DWORD dst_enc,
2042 BYTE* src,
2043 UINT* src_size,
2044 BYTE* dest,
2045 UINT* dest_size)
2046 {
2047 MLang_impl *This = impl_from_IMultiLanguage( iface );
2048 return IMultiLanguage3_ConvertString(&This->IMultiLanguage3_iface, mode, src_enc,
2049 dst_enc, src, src_size, dest, dest_size);
2050 }
2051
2052 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
2053 IMultiLanguage* iface,
2054 DWORD* mode,
2055 DWORD src_enc,
2056 CHAR* src,
2057 UINT* src_size,
2058 WCHAR* dest,
2059 UINT* dest_size)
2060 {
2061 MLang_impl *This = impl_from_IMultiLanguage( iface );
2062 return IMultiLanguage3_ConvertStringToUnicode(&This->IMultiLanguage3_iface,
2063 mode, src_enc, src, src_size, dest, dest_size);
2064 }
2065
2066 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
2067 IMultiLanguage* iface,
2068 DWORD* mode,
2069 DWORD encoding,
2070 WCHAR* src,
2071 UINT* src_size,
2072 CHAR* dest,
2073 UINT* dest_size)
2074 {
2075 MLang_impl *This = impl_from_IMultiLanguage(iface);
2076 return IMultiLanguage3_ConvertStringFromUnicode(&This->IMultiLanguage3_iface,
2077 mode, encoding, src, src_size, dest, dest_size);
2078 }
2079
2080 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
2081 IMultiLanguage* iface)
2082 {
2083 MLang_impl *This = impl_from_IMultiLanguage( iface );
2084 return IMultiLanguage3_ConvertStringReset(&This->IMultiLanguage3_iface);
2085 }
2086
2087 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
2088 IMultiLanguage* iface,
2089 LCID lcid,
2090 BSTR* pbstrRfc1766)
2091 {
2092 MLang_impl *This = impl_from_IMultiLanguage(iface);
2093 return IMultiLanguage3_GetRfc1766FromLcid(&This->IMultiLanguage3_iface, lcid, pbstrRfc1766);
2094 }
2095
2096 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
2097 IMultiLanguage* iface,
2098 LCID* locale,
2099 BSTR rfc1766)
2100 {
2101 MLang_impl *This = impl_from_IMultiLanguage(iface);
2102 return IMultiLanguage3_GetLcidFromRfc1766(&This->IMultiLanguage3_iface, locale, rfc1766);
2103 }
2104
2105 /******************************************************************************/
2106
2107 typedef struct tagEnumRfc1766_impl
2108 {
2109 IEnumRfc1766 IEnumRfc1766_iface;
2110 LONG ref;
2111 RFC1766INFO *info;
2112 DWORD total, pos;
2113 } EnumRfc1766_impl;
2114
2115 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
2116 {
2117 return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
2118 }
2119
2120 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
2121 IEnumRfc1766 *iface,
2122 REFIID riid,
2123 void** ppvObject)
2124 {
2125 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2126
2127 TRACE("%p -> %s\n", This, debugstr_guid(riid) );
2128
2129 if (IsEqualGUID(riid, &IID_IUnknown)
2130 || IsEqualGUID(riid, &IID_IEnumRfc1766))
2131 {
2132 IEnumRfc1766_AddRef(iface);
2133 TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
2134 *ppvObject = &This->IEnumRfc1766_iface;
2135 return S_OK;
2136 }
2137
2138 WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
2139 return E_NOINTERFACE;
2140 }
2141
2142 static ULONG WINAPI fnIEnumRfc1766_AddRef(
2143 IEnumRfc1766 *iface)
2144 {
2145 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2146 return InterlockedIncrement(&This->ref);
2147 }
2148
2149 static ULONG WINAPI fnIEnumRfc1766_Release(
2150 IEnumRfc1766 *iface)
2151 {
2152 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2153 ULONG ref = InterlockedDecrement(&This->ref);
2154
2155 TRACE("%p ref = %d\n", This, ref);
2156 if (ref == 0)
2157 {
2158 TRACE("Destroying %p\n", This);
2159 HeapFree(GetProcessHeap(), 0, This->info);
2160 HeapFree(GetProcessHeap(), 0, This);
2161 }
2162 return ref;
2163 }
2164
2165 static HRESULT WINAPI fnIEnumRfc1766_Clone(
2166 IEnumRfc1766 *iface,
2167 IEnumRfc1766 **ppEnum)
2168 {
2169 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2170
2171 FIXME("%p %p\n", This, ppEnum);
2172 return E_NOTIMPL;
2173 }
2174
2175 static HRESULT WINAPI fnIEnumRfc1766_Next(
2176 IEnumRfc1766 *iface,
2177 ULONG celt,
2178 PRFC1766INFO rgelt,
2179 ULONG *pceltFetched)
2180 {
2181 ULONG i;
2182 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2183
2184 TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
2185
2186 if (!pceltFetched) return S_FALSE;
2187 *pceltFetched = 0;
2188
2189 if (!rgelt) return S_FALSE;
2190
2191 if (This->pos + celt > This->total)
2192 celt = This->total - This->pos;
2193
2194 if (!celt) return S_FALSE;
2195
2196 memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
2197 *pceltFetched = celt;
2198 This->pos += celt;
2199
2200 for (i = 0; i < celt; i++)
2201 {
2202 TRACE("#%u: %08x %s %s\n",
2203 i, rgelt[i].lcid,
2204 wine_dbgstr_w(rgelt[i].wszRfc1766),
2205 wine_dbgstr_w(rgelt[i].wszLocaleName));
2206 }
2207 return S_OK;
2208 }
2209
2210 static HRESULT WINAPI fnIEnumRfc1766_Reset(
2211 IEnumRfc1766 *iface)
2212 {
2213 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2214
2215 TRACE("%p\n", This);
2216
2217 This->pos = 0;
2218 return S_OK;
2219 }
2220
2221 static HRESULT WINAPI fnIEnumRfc1766_Skip(
2222 IEnumRfc1766 *iface,
2223 ULONG celt)
2224 {
2225 EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
2226
2227 TRACE("%p %u\n", This, celt);
2228
2229 if (celt >= This->total) return S_FALSE;
2230
2231 This->pos += celt;
2232 return S_OK;
2233 }
2234
2235 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
2236 {
2237 fnIEnumRfc1766_QueryInterface,
2238 fnIEnumRfc1766_AddRef,
2239 fnIEnumRfc1766_Release,
2240 fnIEnumRfc1766_Clone,
2241 fnIEnumRfc1766_Next,
2242 fnIEnumRfc1766_Reset,
2243 fnIEnumRfc1766_Skip
2244 };
2245
2246 struct enum_locales_data
2247 {
2248 RFC1766INFO *info;
2249 DWORD total, allocated;
2250 };
2251
2252 static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
2253 {
2254 WCHAR *end;
2255 struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
2256 RFC1766INFO *info;
2257
2258 TRACE("%s\n", debugstr_w(locale));
2259
2260 if (data->total >= data->allocated)
2261 {
2262 data->allocated += 32;
2263 data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
2264 if (!data->info) return FALSE;
2265 }
2266
2267 info = &data->info[data->total];
2268
2269 info->lcid = strtolW(locale, &end, 16);
2270 if (*end) /* invalid number */
2271 return FALSE;
2272
2273 info->wszRfc1766[0] = 0;
2274 lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
2275
2276 info->wszLocaleName[0] = 0;
2277 GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
2278 TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
2279
2280 data->total++;
2281
2282 return TRUE;
2283 }
2284
2285 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
2286 {
2287 EnumRfc1766_impl *rfc;
2288 struct enum_locales_data data;
2289
2290 TRACE("%04x, %p\n", LangId, ppEnum);
2291
2292 rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
2293 rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
2294 rfc->ref = 1;
2295 rfc->pos = 0;
2296 rfc->total = 0;
2297
2298 data.total = 0;
2299 data.allocated = 160;
2300 data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
2301 if (!data.info)
2302 {
2303 HeapFree(GetProcessHeap(), 0, rfc);
2304 return E_OUTOFMEMORY;
2305 }
2306
2307 TlsSetValue(MLANG_tls_index, &data);
2308 EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
2309 TlsSetValue(MLANG_tls_index, NULL);
2310
2311 TRACE("enumerated %d rfc1766 structures\n", data.total);
2312
2313 if (!data.total)
2314 {
2315 HeapFree(GetProcessHeap(), 0, data.info);
2316 HeapFree(GetProcessHeap(), 0, rfc);
2317 return E_FAIL;
2318 }
2319
2320 rfc->info = data.info;
2321 rfc->total = data.total;
2322
2323 *ppEnum = &rfc->IEnumRfc1766_iface;
2324 return S_OK;
2325 }
2326
2327 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
2328 IMultiLanguage *iface,
2329 IEnumRfc1766 **ppEnumRfc1766)
2330 {
2331 MLang_impl *This = impl_from_IMultiLanguage( iface );
2332
2333 TRACE("%p %p\n", This, ppEnumRfc1766);
2334
2335 return EnumRfc1766_create(0, ppEnumRfc1766);
2336 }
2337
2338 /******************************************************************************/
2339
2340 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
2341 IMultiLanguage* iface,
2342 LCID Locale,
2343 PRFC1766INFO pRfc1766Info)
2344 {
2345 LCTYPE type = LOCALE_SLANGUAGE;
2346
2347 TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
2348
2349 if (!pRfc1766Info)
2350 return E_INVALIDARG;
2351
2352 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2353 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2354 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2355
2356 if (!SUBLANGID(Locale))
2357 type = LOCALE_SENGLANGUAGE; /* suppress country */
2358 }
2359 else
2360 {
2361 if (!SUBLANGID(Locale)) {
2362 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2363 return E_FAIL;
2364 }
2365 }
2366
2367 pRfc1766Info->lcid = Locale;
2368 pRfc1766Info->wszRfc1766[0] = 0;
2369 pRfc1766Info->wszLocaleName[0] = 0;
2370
2371 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2372 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2373 return S_OK;
2374
2375 /* Locale not supported */
2376 return E_INVALIDARG;
2377 }
2378
2379 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
2380 IMultiLanguage* iface,
2381 UINT src_cp,
2382 UINT dst_cp,
2383 DWORD prop,
2384 IMLangConvertCharset** convert_charset)
2385 {
2386 MLang_impl *This = impl_from_IMultiLanguage(iface);
2387 return IMultiLanguage3_CreateConvertCharset(&This->IMultiLanguage3_iface, src_cp, dst_cp, prop, convert_charset);
2388 }
2389
2390 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
2391 {
2392 fnIMultiLanguage_QueryInterface,
2393 fnIMultiLanguage_AddRef,
2394 fnIMultiLanguage_Release,
2395 fnIMultiLanguage_GetNumberOfCodePageInfo,
2396 fnIMultiLanguage_GetCodePageInfo,
2397 fnIMultiLanguage_GetFamilyCodePage,
2398 fnIMultiLanguage_EnumCodePages,
2399 fnIMultiLanguage_GetCharsetInfo,
2400 fnIMultiLanguage_IsConvertible,
2401 fnIMultiLanguage_ConvertString,
2402 fnIMultiLanguage_ConvertStringToUnicode,
2403 fnIMultiLanguage_ConvertStringFromUnicode,
2404 fnIMultiLanguage_ConvertStringReset,
2405 fnIMultiLanguage_GetRfc1766FromLcid,
2406 fnIMultiLanguage_GetLcidFromRfc1766,
2407 fnIMultiLanguage_EnumRfc1766,
2408 fnIMultiLanguage_GetRfc1766Info,
2409 fnIMultiLanguage_CreateConvertCharset,
2410 };
2411
2412
2413 /******************************************************************************/
2414
2415 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
2416 {
2417 return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
2418 }
2419
2420 static HRESULT WINAPI fnIMultiLanguage3_QueryInterface(
2421 IMultiLanguage3* iface,
2422 REFIID riid,
2423 void** obj)
2424 {
2425 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2426
2427 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2428
2429 if (IsEqualGUID(riid, &IID_IUnknown) ||
2430 IsEqualGUID(riid, &IID_IMultiLanguage))
2431 {
2432 *obj = &This->IMultiLanguage_iface;
2433 }
2434 else if (IsEqualGUID(riid, &IID_IMLangCodePages) ||
2435 IsEqualGUID(riid, &IID_IMLangFontLink))
2436 {
2437 *obj = &This->IMLangFontLink_iface;
2438 }
2439 else if (IsEqualGUID(riid, &IID_IMLangFontLink2))
2440 {
2441 *obj = &This->IMLangFontLink2_iface;
2442 }
2443 else if (IsEqualGUID(riid, &IID_IMultiLanguage2) ||
2444 IsEqualGUID(riid, &IID_IMultiLanguage3))
2445 {
2446 *obj = &This->IMultiLanguage3_iface;
2447 }
2448 else if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
2449 {
2450 *obj = &This->IMLangLineBreakConsole_iface;
2451 }
2452 else
2453 {
2454 WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), obj);
2455 *obj = NULL;
2456 return E_NOINTERFACE;
2457 }
2458
2459 IMultiLanguage3_AddRef(iface);
2460 return S_OK;
2461 }
2462
2463 static ULONG WINAPI fnIMultiLanguage3_AddRef( IMultiLanguage3* iface )
2464 {
2465 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2466 return InterlockedIncrement(&This->ref);
2467 }
2468
2469 static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
2470 {
2471 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2472 ULONG ref = InterlockedDecrement(&This->ref);
2473
2474 TRACE("(%p)->(%d)\n", This, ref);
2475 if (ref == 0)
2476 {
2477 HeapFree(GetProcessHeap(), 0, This);
2478 UnlockModule();
2479 }
2480
2481 return ref;
2482 }
2483
2484 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfCodePageInfo(
2485 IMultiLanguage3* iface,
2486 UINT* pcCodePage)
2487 {
2488 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2489
2490 TRACE("%p, %p\n", This, pcCodePage);
2491
2492 if (!pcCodePage) return E_INVALIDARG;
2493
2494 *pcCodePage = This->total_cp;
2495 return S_OK;
2496 }
2497
2498 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
2499 {
2500 CHARSETINFO csi;
2501
2502 if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
2503 TCI_SRCCODEPAGE))
2504 mime_cp_info->bGDICharset = csi.ciCharset;
2505 else
2506 mime_cp_info->bGDICharset = DEFAULT_CHARSET;
2507
2508 mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
2509 mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
2510 mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
2511 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
2512 mime_cp_info->wszDescription, sizeof(mime_cp_info->wszDescription)/sizeof(WCHAR));
2513 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
2514 mime_cp_info->wszWebCharset, sizeof(mime_cp_info->wszWebCharset)/sizeof(WCHAR));
2515 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
2516 mime_cp_info->wszHeaderCharset, sizeof(mime_cp_info->wszHeaderCharset)/sizeof(WCHAR));
2517 MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
2518 mime_cp_info->wszBodyCharset, sizeof(mime_cp_info->wszBodyCharset)/sizeof(WCHAR));
2519
2520 MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
2521 mime_cp_info->wszFixedWidthFont, sizeof(mime_cp_info->wszFixedWidthFont)/sizeof(WCHAR));
2522 MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
2523 mime_cp_info->wszProportionalFont, sizeof(mime_cp_info->wszProportionalFont)/sizeof(WCHAR));
2524
2525 TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
2526 mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
2527 mime_cp_info->uiFamilyCodePage,
2528 wine_dbgstr_w(mime_cp_info->wszDescription),
2529 wine_dbgstr_w(mime_cp_info->wszWebCharset),
2530 wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
2531 wine_dbgstr_w(mime_cp_info->wszBodyCharset),
2532 wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
2533 wine_dbgstr_w(mime_cp_info->wszProportionalFont),
2534 mime_cp_info->bGDICharset);
2535 }
2536
2537 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageInfo(
2538 IMultiLanguage3* iface,
2539 UINT uiCodePage,
2540 LANGID LangId,
2541 PMIMECPINFO pCodePageInfo)
2542 {
2543 UINT i, n;
2544 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2545
2546 TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
2547
2548 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2549 {
2550 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2551 {
2552 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2553 {
2554 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
2555 return S_OK;
2556 }
2557 }
2558 }
2559
2560 return S_FALSE;
2561 }
2562
2563 static HRESULT WINAPI fnIMultiLanguage3_GetFamilyCodePage(
2564 IMultiLanguage3* iface,
2565 UINT uiCodePage,
2566 UINT* puiFamilyCodePage)
2567 {
2568 return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
2569 }
2570
2571 static HRESULT WINAPI fnIMultiLanguage3_EnumCodePages(
2572 IMultiLanguage3* iface,
2573 DWORD grfFlags,
2574 LANGID LangId,
2575 IEnumCodePage** ppEnumCodePage)
2576 {
2577 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2578
2579 TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
2580
2581 return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
2582 }
2583
2584 static HRESULT WINAPI fnIMultiLanguage3_GetCharsetInfo(
2585 IMultiLanguage3* iface,
2586 BSTR Charset,
2587 PMIMECSETINFO pCharsetInfo)
2588 {
2589 UINT i, n;
2590 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2591
2592 TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
2593
2594 if (!pCharsetInfo) return E_FAIL;
2595
2596 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2597 {
2598 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2599 {
2600 WCHAR csetW[MAX_MIMECSET_NAME];
2601
2602 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
2603 if (!lstrcmpiW(Charset, csetW))
2604 {
2605 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2606 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2607 strcpyW(pCharsetInfo->wszCharset, csetW);
2608 return S_OK;
2609 }
2610 if (mlang_data[i].mime_cp_info[n].alias && !lstrcmpiW(Charset, mlang_data[i].mime_cp_info[n].alias))
2611 {
2612 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2613 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2614 strcpyW(pCharsetInfo->wszCharset, mlang_data[i].mime_cp_info[n].alias);
2615 return S_OK;
2616 }
2617 }
2618 }
2619
2620 /* FIXME:
2621 * Since we do not support charsets like iso-2022-jp and do not have
2622 * them in our database as a primary (web_charset) encoding this loop
2623 * does an attempt to 'approximate' charset name by header_charset.
2624 */
2625 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2626 {
2627 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2628 {
2629 WCHAR csetW[MAX_MIMECSET_NAME];
2630
2631 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
2632 if (!lstrcmpiW(Charset, csetW))
2633 {
2634 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
2635 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
2636 strcpyW(pCharsetInfo->wszCharset, csetW);
2637 return S_OK;
2638 }
2639 }
2640 }
2641
2642 return E_FAIL;
2643 }
2644
2645 static HRESULT WINAPI fnIMultiLanguage3_IsConvertible(
2646 IMultiLanguage3* iface,
2647 DWORD dwSrcEncoding,
2648 DWORD dwDstEncoding)
2649 {
2650 return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
2651 }
2652
2653 static HRESULT WINAPI fnIMultiLanguage3_ConvertString(
2654 IMultiLanguage3* iface,
2655 DWORD* pdwMode,
2656 DWORD dwSrcEncoding,
2657 DWORD dwDstEncoding,
2658 BYTE* pSrcStr,
2659 UINT* pcSrcSize,
2660 BYTE* pDstStr,
2661 UINT* pcDstSize)
2662 {
2663 return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
2664 (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
2665 }
2666
2667 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicode(
2668 IMultiLanguage3* iface,
2669 DWORD* pdwMode,
2670 DWORD dwEncoding,
2671 CHAR* pSrcStr,
2672 UINT* pcSrcSize,
2673 WCHAR* pDstStr,
2674 UINT* pcDstSize)
2675 {
2676 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2677 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2678 }
2679
2680 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicode(
2681 IMultiLanguage3* iface,
2682 DWORD* pdwMode,
2683 DWORD dwEncoding,
2684 WCHAR* pSrcStr,
2685 UINT* pcSrcSize,
2686 CHAR* pDstStr,
2687 UINT* pcDstSize)
2688 {
2689 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2690 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2691 }
2692
2693 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringReset(
2694 IMultiLanguage3* iface)
2695 {
2696 FIXME("\n");
2697 return E_NOTIMPL;
2698 }
2699
2700 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766FromLcid(
2701 IMultiLanguage3* iface,
2702 LCID lcid,
2703 BSTR* pbstrRfc1766)
2704 {
2705 WCHAR buf[MAX_RFC1766_NAME];
2706
2707 TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
2708 if (!pbstrRfc1766)
2709 return E_INVALIDARG;
2710
2711 if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
2712 {
2713 *pbstrRfc1766 = SysAllocString( buf );
2714 return S_OK;
2715 }
2716 return E_FAIL;
2717 }
2718
2719 static HRESULT WINAPI fnIMultiLanguage3_GetLcidFromRfc1766(
2720 IMultiLanguage3* iface,
2721 LCID* pLocale,
2722 BSTR bstrRfc1766)
2723 {
2724 HRESULT hr;
2725 IEnumRfc1766 *rfc1766;
2726
2727 TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
2728
2729 if (!pLocale || !bstrRfc1766)
2730 return E_INVALIDARG;
2731
2732 hr = IMultiLanguage3_EnumRfc1766(iface, 0, &rfc1766);
2733 if (FAILED(hr))
2734 return hr;
2735
2736 hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
2737
2738 IEnumRfc1766_Release(rfc1766);
2739 return hr;
2740 }
2741
2742 static HRESULT WINAPI fnIMultiLanguage3_EnumRfc1766(
2743 IMultiLanguage3* iface,
2744 LANGID LangId,
2745 IEnumRfc1766** ppEnumRfc1766)
2746 {
2747 MLang_impl *This = impl_from_IMultiLanguage3( iface );
2748
2749 TRACE("%p %p\n", This, ppEnumRfc1766);
2750
2751 return EnumRfc1766_create(LangId, ppEnumRfc1766);
2752 }
2753
2754 static HRESULT WINAPI fnIMultiLanguage3_GetRfc1766Info(
2755 IMultiLanguage3* iface,
2756 LCID Locale,
2757 LANGID LangId,
2758 PRFC1766INFO pRfc1766Info)
2759 {
2760 static LANGID last_lang = -1;
2761 LCTYPE type = LOCALE_SLANGUAGE;
2762
2763 TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
2764
2765 if (!pRfc1766Info)
2766 return E_INVALIDARG;
2767
2768 if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
2769 (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
2770 (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
2771
2772 if (!SUBLANGID(Locale))
2773 type = LOCALE_SENGLANGUAGE; /* suppress country */
2774 }
2775 else
2776 {
2777 if (!SUBLANGID(Locale)) {
2778 TRACE("SUBLANGID missing in 0x%04x\n", Locale);
2779 return E_FAIL;
2780 }
2781 }
2782
2783 pRfc1766Info->lcid = Locale;
2784 pRfc1766Info->wszRfc1766[0] = 0;
2785 pRfc1766Info->wszLocaleName[0] = 0;
2786
2787 if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
2788 (last_lang != LangId)) {
2789 FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
2790 last_lang = LangId;
2791 }
2792
2793 if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
2794 (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
2795 return S_OK;
2796
2797 /* Locale not supported */
2798 return E_INVALIDARG;
2799 }
2800
2801 static HRESULT WINAPI fnIMultiLanguage3_CreateConvertCharset(
2802 IMultiLanguage3* iface,
2803 UINT src_cp,
2804 UINT dst_cp,
2805 DWORD prop,
2806 IMLangConvertCharset** convert_charset)
2807 {
2808 HRESULT hr;
2809
2810 TRACE("(%u %u 0x%08x %p)\n", src_cp, dst_cp, prop, convert_charset);
2811
2812 hr = MLangConvertCharset_create(NULL, (void**)convert_charset);
2813 if (FAILED(hr)) return hr;
2814
2815 return IMLangConvertCharset_Initialize(*convert_charset, src_cp, dst_cp, prop);
2816 }
2817
2818 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringInIStream(
2819 IMultiLanguage3* iface,
2820 DWORD* pdwMode,
2821 DWORD dwFlag,
2822 WCHAR* lpFallBack,
2823 DWORD dwSrcEncoding,
2824 DWORD dwDstEncoding,
2825 IStream* pstmIn,
2826 IStream* pstmOut)
2827 {
2828 char *src, *dst = NULL;
2829 INT srclen, dstlen;
2830 STATSTG stat;
2831 HRESULT hr;
2832
2833 TRACE("%p %0x8 %s %u %u %p %p\n",
2834 pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
2835
2836 FIXME("dwFlag and lpFallBack not handled\n");
2837
2838 hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
2839 if (FAILED(hr)) return hr;
2840
2841 if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
2842 if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
2843
2844 hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
2845 if (FAILED(hr)) goto exit;
2846
2847 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
2848 if (FAILED(hr)) goto exit;
2849
2850 if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
2851 {
2852 hr = E_OUTOFMEMORY;
2853 goto exit;
2854 }
2855 hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
2856 if (FAILED(hr)) goto exit;
2857
2858 hr = IStream_Write(pstmOut, dst, dstlen, NULL);
2859
2860 exit:
2861 HeapFree(GetProcessHeap(), 0, src);
2862 HeapFree(GetProcessHeap(), 0, dst);
2863 return hr;
2864 }
2865
2866 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringToUnicodeEx(
2867 IMultiLanguage3* iface,
2868 DWORD* pdwMode,
2869 DWORD dwEncoding,
2870 CHAR* pSrcStr,
2871 UINT* pcSrcSize,
2872 WCHAR* pDstStr,
2873 UINT* pcDstSize,
2874 DWORD dwFlag,
2875 WCHAR* lpFallBack)
2876 {
2877 if (dwFlag || lpFallBack)
2878 FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
2879 dwFlag, dwFlag, lpFallBack);
2880
2881 return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
2882 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2883 }
2884
2885 /*****************************************************************************
2886 * MultiLanguage2::ConvertStringToUnicodeEx
2887 *
2888 * Translates the multibyte string from the specified code page to Unicode.
2889 *
2890 * PARAMS
2891 * see ConvertStringToUnicode
2892 * dwFlag
2893 * lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
2894 * instead unconvertible characters.
2895 *
2896 * RETURNS
2897 * S_OK Success.
2898 * S_FALSE The conversion is not supported.
2899 * E_FAIL Some error has occurred.
2900 *
2901 * TODO: handle dwFlag and lpFallBack
2902 */
2903 static HRESULT WINAPI fnIMultiLanguage3_ConvertStringFromUnicodeEx(
2904 IMultiLanguage3* This,
2905 DWORD* pdwMode,
2906 DWORD dwEncoding,
2907 WCHAR* pSrcStr,
2908 UINT* pcSrcSize,
2909 CHAR* pDstStr,
2910 UINT* pcDstSize,
2911 DWORD dwFlag,
2912 WCHAR* lpFallBack)
2913 {
2914 FIXME("\n");
2915 return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
2916 pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
2917 }
2918
2919 static HRESULT WINAPI fnIMultiLanguage3_DetectCodepageInIStream(
2920 IMultiLanguage3* iface,
2921 DWORD dwFlag,
2922 DWORD dwPrefWinCodePage,
2923 IStream* pstmIn,
2924 DetectEncodingInfo* lpEncoding,
2925 INT* pnScores)
2926 {
2927 FIXME("\n");
2928 return E_NOTIMPL;
2929 }
2930
2931 static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
2932 IMultiLanguage3* iface,
2933 DWORD dwFlag,
2934 DWORD dwPrefWinCodePage,
2935 CHAR* pSrcStr,
2936 INT* pcSrcSize,
2937 DetectEncodingInfo* lpEncoding,
2938 INT* pnScores)
2939 {
2940 FIXME("\n");
2941 return E_NOTIMPL;
2942 }
2943
2944 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
2945 IMultiLanguage3* iface,
2946 UINT uiCodePage,
2947 HWND hwnd)
2948 {
2949 return IMultiLanguage3_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
2950 }
2951
2952 static HRESULT WINAPI fnIMultiLanguage3_GetCodePageDescription(
2953 IMultiLanguage3* iface,
2954 UINT uiCodePage,
2955 LCID lcid,
2956 LPWSTR lpWideCharStr,
2957 int cchWideChar)
2958 {
2959 /* Find first instance */
2960 unsigned int i,n;
2961
2962 TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
2963 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
2964 {
2965 for (n = 0; n < mlang_data[i].number_of_cp; n++)
2966 {
2967 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
2968 {
2969 MultiByteToWideChar(CP_ACP, 0,
2970 mlang_data[i].mime_cp_info[n].description,
2971 -1, lpWideCharStr, cchWideChar);
2972 return S_OK;
2973 }
2974 }
2975 }
2976
2977 return S_FALSE;
2978 }
2979
2980 static HRESULT WINAPI fnIMultiLanguage3_IsCodePageInstallable(
2981 IMultiLanguage3* iface,
2982 UINT uiCodePage)
2983 {
2984 TRACE("%u\n", uiCodePage);
2985
2986 /* FIXME: the installable set is usually larger than the set of valid codepages */
2987 return IMultiLanguage3_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
2988 }
2989
2990 static HRESULT WINAPI fnIMultiLanguage3_SetMimeDBSource(
2991 IMultiLanguage3* iface,
2992 MIMECONTF dwSource)
2993 {
2994 FIXME("0x%08x\n", dwSource);
2995 return S_OK;
2996 }
2997
2998 static HRESULT WINAPI fnIMultiLanguage3_GetNumberOfScripts(
2999 IMultiLanguage3* iface,
3000 UINT* pnScripts)
3001 {
3002 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3003
3004 TRACE("%p %p\n", This, pnScripts);
3005
3006 if (!pnScripts) return S_FALSE;
3007
3008 *pnScripts = This->total_scripts;
3009 return S_OK;
3010 }
3011
3012 static HRESULT WINAPI fnIMultiLanguage3_EnumScripts(
3013 IMultiLanguage3* iface,
3014 DWORD dwFlags,
3015 LANGID LangId,
3016 IEnumScript** ppEnumScript)
3017 {
3018 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3019
3020 TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
3021
3022 return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
3023 }
3024
3025 static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePageEx(
3026 IMultiLanguage3* iface,
3027 UINT uiCodePage,
3028 HWND hwnd,
3029 DWORD dwfIODControl)
3030 {
3031 unsigned int i;
3032 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3033
3034 TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
3035
3036 /* quick check for kernel32 supported code pages */
3037 if (IsValidCodePage(uiCodePage))
3038 return S_OK;
3039
3040 /* check for mlang supported code pages */
3041 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3042 {
3043 UINT n;
3044 for (n = 0; n < mlang_data[i].number_of_cp; n++)
3045 {
3046 if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
3047 return S_OK;
3048 }
3049 }
3050
3051 if (dwfIODControl != CPIOD_PEEK)
3052 FIXME("Request to install codepage language pack not handled\n");
3053
3054 return S_FALSE;
3055 }
3056
3057 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
3058 IMultiLanguage3 *iface,
3059 DWORD dwFlags,
3060 LPCWSTR lpWideCharStr,
3061 UINT cchWideChar,
3062 UINT *puiPreferredCodePages,
3063 UINT nPreferredCodePages,
3064 UINT *puiDetectedCodePages,
3065 UINT *pnDetectedCodePages,
3066 WCHAR *lpSpecialChar)
3067 {
3068 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3069
3070 FIXME("(%p)->(%08x %s %p %u %p %p(%u) %s)\n", This, dwFlags, debugstr_w(lpWideCharStr),
3071 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3072 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3073 debugstr_w(lpSpecialChar));
3074
3075 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3076 return E_INVALIDARG;
3077
3078 puiDetectedCodePages[0] = CP_UTF8;
3079 *pnDetectedCodePages = 1;
3080 return S_OK;
3081 }
3082
3083 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
3084 IMultiLanguage3 *iface,
3085 DWORD dwFlags,
3086 IStream *pStrIn,
3087 UINT *puiPreferredCodePages,
3088 UINT nPreferredCodePages,
3089 UINT *puiDetectedCodePages,
3090 UINT *pnDetectedCodePages,
3091 WCHAR *lpSpecialChar)
3092 {
3093 MLang_impl *This = impl_from_IMultiLanguage3( iface );
3094
3095 FIXME("(%p)->(%08x %p %p %u %p %p(%u) %s)\n", This, dwFlags, pStrIn,
3096 puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
3097 pnDetectedCodePages, pnDetectedCodePages ? *pnDetectedCodePages : 0,
3098 debugstr_w(lpSpecialChar));
3099
3100 if (!puiDetectedCodePages || !pnDetectedCodePages || !*pnDetectedCodePages)
3101 return E_INVALIDARG;
3102
3103 puiDetectedCodePages[0] = CP_UTF8;
3104 *pnDetectedCodePages = 1;
3105 return S_OK;
3106 }
3107
3108 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
3109 {
3110 fnIMultiLanguage3_QueryInterface,
3111 fnIMultiLanguage3_AddRef,
3112 fnIMultiLanguage3_Release,
3113 fnIMultiLanguage3_GetNumberOfCodePageInfo,
3114 fnIMultiLanguage3_GetCodePageInfo,
3115 fnIMultiLanguage3_GetFamilyCodePage,
3116 fnIMultiLanguage3_EnumCodePages,
3117 fnIMultiLanguage3_GetCharsetInfo,
3118 fnIMultiLanguage3_IsConvertible,
3119 fnIMultiLanguage3_ConvertString,
3120 fnIMultiLanguage3_ConvertStringToUnicode,
3121 fnIMultiLanguage3_ConvertStringFromUnicode,
3122 fnIMultiLanguage3_ConvertStringReset,
3123 fnIMultiLanguage3_GetRfc1766FromLcid,
3124 fnIMultiLanguage3_GetLcidFromRfc1766,
3125 fnIMultiLanguage3_EnumRfc1766,
3126 fnIMultiLanguage3_GetRfc1766Info,
3127 fnIMultiLanguage3_CreateConvertCharset,
3128 fnIMultiLanguage3_ConvertStringInIStream,
3129 fnIMultiLanguage3_ConvertStringToUnicodeEx,
3130 fnIMultiLanguage3_ConvertStringFromUnicodeEx,
3131 fnIMultiLanguage3_DetectCodepageInIStream,
3132 fnIMultiLanguage3_DetectInputCodepage,
3133 fnIMultiLanguage3_ValidateCodePage,
3134 fnIMultiLanguage3_GetCodePageDescription,
3135 fnIMultiLanguage3_IsCodePageInstallable,
3136 fnIMultiLanguage3_SetMimeDBSource,
3137 fnIMultiLanguage3_GetNumberOfScripts,
3138 fnIMultiLanguage3_EnumScripts,
3139 fnIMultiLanguage3_ValidateCodePageEx,
3140 fnIMultiLanguage3_DetectOutboundCodePage,
3141 fnIMultiLanguage3_DetectOutboundCodePageInIStream
3142 };
3143
3144 /******************************************************************************/
3145
3146 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
3147 {
3148 return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
3149 }
3150
3151 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
3152 IMLangFontLink2 * iface,
3153 REFIID riid,
3154 void** ppvObject)
3155 {
3156 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3157 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3158 }
3159
3160 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
3161 {
3162 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3163 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3164 }
3165
3166 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
3167 {
3168 MLang_impl *This = impl_from_IMLangFontLink2( iface );
3169 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3170 }
3171
3172 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* iface,
3173 WCHAR ch_src, DWORD *ret_codepages)
3174 {
3175 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3176 unsigned int i;
3177
3178 TRACE("(%p)->(%s %p)\n", This, debugstr_wn(&ch_src, 1), ret_codepages);
3179
3180 *ret_codepages = 0;
3181
3182 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3183 {
3184 BOOL used_dc;
3185 CHAR buf;
3186
3187 WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
3188 &ch_src, 1, &buf, 1, NULL, &used_dc);
3189
3190 /* If default char is not used, current codepage include the given symbol */
3191 if (!used_dc)
3192 {
3193 DWORD codepages;
3194
3195 IMLangFontLink2_CodePageToCodePages(iface,
3196 mlang_data[i].family_codepage, &codepages);
3197 *ret_codepages |= codepages;
3198 }
3199 }
3200 return S_OK;
3201 }
3202
3203 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* iface,
3204 const WCHAR *src, LONG src_len, DWORD priority_cp,
3205 DWORD *codepages, LONG *ret_len)
3206 {
3207 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3208 LONG i;
3209 DWORD cps = 0;
3210
3211 TRACE("(%p)->(%s:%d %x %p %p)\n", This, debugstr_wn(src, src_len), src_len, priority_cp,
3212 codepages, ret_len);
3213
3214 if (codepages) *codepages = 0;
3215 if (ret_len) *ret_len = 0;
3216
3217 if (!src || !src_len || src_len < 0)
3218 return E_INVALIDARG;
3219
3220 for (i = 0; i < src_len; i++)
3221 {
3222 DWORD cp;
3223 HRESULT ret;
3224
3225 ret = IMLangFontLink2_GetCharCodePages(iface, src[i], &cp);
3226 if (ret != S_OK) return E_FAIL;
3227
3228 if (!cps) cps = cp;
3229 else cps &= cp;
3230
3231 /* FIXME: not tested */
3232 if (priority_cp & cps) break;
3233 }
3234
3235 if (codepages) *codepages = cps;
3236 if (ret_len) *ret_len = min( i + 1, src_len );
3237 return S_OK;
3238 }
3239
3240 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* iface,
3241 UINT codepage,
3242 DWORD *codepages)
3243 {
3244 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3245 CHARSETINFO cs;
3246 BOOL rc;
3247
3248 TRACE("(%p)->(%u %p)\n", This, codepage, codepages);
3249
3250 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)codepage, &cs, TCI_SRCCODEPAGE);
3251 if (rc)
3252 {
3253 *codepages = cs.fs.fsCsb[0];
3254 TRACE("resulting codepages 0x%x\n", *codepages);
3255 return S_OK;
3256 }
3257
3258 TRACE("codepage not found\n");
3259 *codepages = 0;
3260 return E_FAIL;
3261 }
3262
3263 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* iface,
3264 DWORD codepages, UINT def_codepage, UINT *codepage)
3265 {
3266 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3267 DWORD mask = 0;
3268 CHARSETINFO cs;
3269 BOOL rc;
3270 UINT i;
3271
3272 TRACE("(%p)->(0x%x %u %p)\n", This, codepages, def_codepage, codepage);
3273
3274 *codepage = 0;
3275
3276 rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)def_codepage, &cs, TCI_SRCCODEPAGE);
3277 if (rc && (codepages & cs.fs.fsCsb[0]))
3278 {
3279 TRACE("Found Default Codepage\n");
3280 *codepage = def_codepage;
3281 return S_OK;
3282 }
3283
3284 for (i = 0; i < 32; i++)
3285 {
3286 mask = 1 << i;
3287 if (codepages & mask)
3288 {
3289 DWORD Csb[2];
3290 Csb[0] = mask;
3291 Csb[1] = 0x0;
3292 rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
3293 if (!rc)
3294 continue;
3295
3296 TRACE("Falling back to least significant found CodePage %u\n",
3297 cs.ciACP);
3298 *codepage = cs.ciACP;
3299 return S_OK;
3300 }
3301 }
3302
3303 TRACE("no codepage found\n");
3304 return E_FAIL;
3305 }
3306
3307 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
3308 HDC hdc, HFONT hfont, DWORD *codepages)
3309 {
3310 MLang_impl *This = impl_from_IMLangFontLink2(iface);
3311 FONTSIGNATURE fontsig;
3312 HFONT old_font;
3313
3314 TRACE("(%p)->(%p %p %p)\n", This, hdc, hfont, codepages);
3315
3316 old_font = SelectObject(hdc, hfont);
3317 GetTextCharsetInfo(hdc, &fontsig, 0);
3318 SelectObject(hdc, old_font);
3319
3320 *codepages = fontsig.fsCsb[0];
3321 TRACE("ret 0x%x\n", fontsig.fsCsb[0]);
3322
3323 return S_OK;
3324 }
3325
3326 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
3327 HFONT hFont)
3328 {
3329 FIXME("(%p)->%p\n",This, hFont);
3330 return E_NOTIMPL;
3331 }
3332
3333 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
3334 {
3335 FIXME("(%p)->\n",This);
3336 return E_NOTIMPL;
3337 }
3338
3339 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
3340 HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
3341 {
3342 FIXME("(%p)->%p %i %s %p\n",This, hDC, dwCodePages, debugstr_wn(&chSrc,1), pFont);
3343 return E_NOTIMPL;
3344 }
3345
3346 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
3347 HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
3348 {
3349 DWORD size;
3350 GLYPHSET *gs;
3351
3352 TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
3353
3354 if (!puiRanges) return E_INVALIDARG;
3355 if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
3356 if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
3357
3358 GetFontUnicodeRanges(hDC, gs);
3359 *puiRanges = gs->cRanges;
3360 if (pUranges)
3361 {
3362 UINT i;
3363 for (i = 0; i < gs->cRanges; i++)
3364 {
3365 if (i >= *puiRanges) break;
3366 pUranges[i].wcFrom = gs->ranges[i].wcLow;
3367 pUranges[i].wcTo = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
3368 }
3369 *puiRanges = i;
3370 }
3371 HeapFree(GetProcessHeap(), 0, gs);
3372 return S_OK;
3373 }
3374
3375 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
3376 SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
3377 SCRIPTFONTINFO *pScriptFont)
3378 {
3379 UINT i, j;
3380
3381 TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
3382
3383 if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
3384
3385 for (i = 0, j = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3386 {
3387 if (sid == mlang_data[i].sid)
3388 {
3389 if (pScriptFont)
3390 {
3391 if (j >= *puiFonts) break;
3392
3393 pScriptFont[j].scripts = 1 << mlang_data[i].sid;
3394 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
3395 {
3396 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
3397 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3398 }
3399 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
3400 {
3401 MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
3402 pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
3403 }
3404 }
3405 j++;
3406 }
3407 }
3408 *puiFonts = j;
3409 return S_OK;
3410 }
3411
3412 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
3413 UINT uiCodePage, SCRIPT_ID *pSid)
3414 {
3415 UINT i;
3416
3417 TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
3418
3419 if (uiCodePage == CP_UNICODE) return E_FAIL;
3420
3421 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3422 {
3423 if (uiCodePage == mlang_data[i].family_codepage)
3424 {
3425 if (pSid) *pSid = mlang_data[i].sid;
3426 return S_OK;
3427 }
3428 }
3429 return E_FAIL;
3430 }
3431
3432 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
3433 {
3434 fnIMLangFontLink2_QueryInterface,
3435 fnIMLangFontLink2_AddRef,
3436 fnIMLangFontLink2_Release,
3437 fnIMLangFontLink2_GetCharCodePages,
3438 fnIMLangFontLink2_GetStrCodePages,
3439 fnIMLangFontLink2_CodePageToCodePages,
3440 fnIMLangFontLink2_CodePagesToCodePage,
3441 fnIMLangFontLink2_GetFontCodePages,
3442 fnIMLangFontLink2_ReleaseFont,
3443 fnIMLangFontLink2_ResetFontMapping,
3444 fnIMLangFontLink2_MapFont,
3445 fnIMLangFontLink2_GetFontUnicodeRanges,
3446 fnIMLangFontLink2_GetScriptFontInfo,
3447 fnIMLangFontLink2_CodePageToScriptID
3448 };
3449
3450 /******************************************************************************/
3451
3452 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
3453 {
3454 return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
3455 }
3456
3457 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
3458 IMLangLineBreakConsole* iface,
3459 REFIID riid,
3460 void** ppvObject)
3461 {
3462 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3463 return IMultiLanguage3_QueryInterface( &This->IMultiLanguage3_iface, riid, ppvObject );
3464 }
3465
3466 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
3467 IMLangLineBreakConsole* iface )
3468 {
3469 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3470 return IMultiLanguage3_AddRef( &This->IMultiLanguage3_iface );
3471 }
3472
3473 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
3474 IMLangLineBreakConsole* iface )
3475 {
3476 MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
3477 return IMultiLanguage3_Release( &This->IMultiLanguage3_iface );
3478 }
3479
3480 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
3481 IMLangLineBreakConsole* iface,
3482 IMLangString* pSrcMLStr,
3483 LONG lSrcPos,
3484 LONG lSrcLen,
3485 LONG cMinColumns,
3486 LONG cMaxColumns,
3487 LONG* plLineLen,
3488 LONG* plSkipLen)
3489 {
3490 FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
3491 return E_NOTIMPL;
3492 }
3493
3494 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
3495 IMLangLineBreakConsole* iface,
3496 LCID locale,
3497 const WCHAR* pszSrc,
3498 LONG cchSrc,
3499 LONG cMaxColumns,
3500 LONG* pcchLine,
3501 LONG* pcchSkip )
3502 {
3503 FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3504
3505 *pcchLine = cchSrc;
3506 *pcchSkip = 0;
3507 return S_OK;
3508 }
3509
3510 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
3511 IMLangLineBreakConsole* iface,
3512 LCID locale,
3513 UINT uCodePage,
3514 const CHAR* pszSrc,
3515 LONG cchSrc,
3516 LONG cMaxColumns,
3517 LONG* pcchLine,
3518 LONG* pcchSkip)
3519 {
3520 LONG i, line = cchSrc, skip = 0;
3521
3522 FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
3523
3524 if (uCodePage == CP_USASCII && cchSrc > cMaxColumns)
3525 {
3526 for (line = cMaxColumns, i = cMaxColumns - 1; i >= 0; i--)
3527 {
3528 if (pszSrc[i] == ' ')
3529 {
3530 while (i >= 0 && pszSrc[i] == ' ')
3531 {
3532 i--;
3533 line--;
3534 skip++;
3535 }
3536 break;
3537 }
3538 }
3539 }
3540 *pcchLine = line;
3541 *pcchSkip = skip;
3542 return S_OK;
3543 }
3544
3545 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
3546 {
3547 fnIMLangLineBreakConsole_QueryInterface,
3548 fnIMLangLineBreakConsole_AddRef,
3549 fnIMLangLineBreakConsole_Release,
3550 fnIMLangLineBreakConsole_BreakLineML,
3551 fnIMLangLineBreakConsole_BreakLineW,
3552 fnIMLangLineBreakConsole_BreakLineA
3553 };
3554
3555 struct convert_charset {
3556 IMLangConvertCharset IMLangConvertCharset_iface;
3557 LONG ref;
3558
3559 UINT src_cp;
3560 UINT dst_cp;
3561 };
3562
3563 static inline struct convert_charset *impl_from_IMLangConvertCharset(IMLangConvertCharset *iface)
3564 {
3565 return CONTAINING_RECORD(iface, struct convert_charset, IMLangConvertCharset_iface);
3566 }
3567
3568 static HRESULT WINAPI MLangConvertCharset_QueryInterface(IMLangConvertCharset *iface, REFIID riid, void **obj)
3569 {
3570 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3571
3572 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
3573
3574 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMLangConvertCharset))
3575 {
3576 *obj = &This->IMLangConvertCharset_iface;
3577 IMLangConvertCharset_AddRef(iface);
3578 return S_OK;
3579 }
3580
3581 *obj = NULL;
3582 return E_NOINTERFACE;
3583 }
3584
3585 static ULONG WINAPI MLangConvertCharset_AddRef(IMLangConvertCharset *iface)
3586 {
3587 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3588 ULONG ref = InterlockedIncrement(&This->ref);
3589 TRACE("(%p)->(%u)\n", This, ref);
3590 return ref;
3591 }
3592
3593 static ULONG WINAPI MLangConvertCharset_Release(IMLangConvertCharset *iface)
3594 {
3595 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3596 ULONG ref = InterlockedDecrement(&This->ref);
3597
3598 TRACE("(%p)->(%u)\n", This, ref);
3599 if (!ref)
3600 {
3601 HeapFree(GetProcessHeap(), 0, This);
3602 UnlockModule();
3603 }
3604
3605 return ref;
3606 }
3607
3608 static HRESULT WINAPI MLangConvertCharset_Initialize(IMLangConvertCharset *iface,
3609 UINT src_cp, UINT dst_cp, DWORD prop)
3610 {
3611 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3612
3613 TRACE("(%p)->(%u %u 0x%08x)\n", This, src_cp, dst_cp, prop);
3614
3615 prop &= ~MLCONVCHARF_USEDEFCHAR;
3616 if (prop)
3617 FIXME("property 0x%08x not supported\n", prop);
3618
3619 This->src_cp = src_cp;
3620 This->dst_cp = dst_cp;
3621
3622 return S_OK;
3623 }
3624
3625 static HRESULT WINAPI MLangConvertCharset_GetSourceCodePage(IMLangConvertCharset *iface, UINT *src_cp)
3626 {
3627 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3628
3629 TRACE("(%p)->(%p)\n", This, src_cp);
3630
3631 if (!src_cp) return E_INVALIDARG;
3632 *src_cp = This->src_cp;
3633 return S_OK;
3634 }
3635
3636 static HRESULT WINAPI MLangConvertCharset_GetDestinationCodePage(IMLangConvertCharset *iface, UINT *dst_cp)
3637 {
3638 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3639
3640 TRACE("(%p)->(%p)\n", This, dst_cp);
3641
3642 if (!dst_cp) return E_INVALIDARG;
3643 *dst_cp = This->dst_cp;
3644 return S_OK;
3645 }
3646
3647 static HRESULT WINAPI MLangConvertCharset_GetProperty(IMLangConvertCharset *iface, DWORD *prop)
3648 {
3649 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3650 FIXME("(%p)->(%p): stub\n", This, prop);
3651 return E_NOTIMPL;
3652 }
3653
3654 static HRESULT WINAPI MLangConvertCharset_DoConversion(IMLangConvertCharset *iface, BYTE *src,
3655 UINT *src_size, BYTE *dest, UINT *dest_size)
3656 {
3657 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3658 FIXME("(%p)->(%p %p %p %p): stub\n", This, src, src_size, dest, dest_size);
3659 return E_NOTIMPL;
3660 }
3661
3662 static HRESULT WINAPI MLangConvertCharset_DoConversionToUnicode(IMLangConvertCharset *iface, CHAR *src,
3663 UINT *src_size, WCHAR *dest, UINT *dest_size)
3664 {
3665 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3666 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3667 return ConvertINetMultiByteToUnicode(NULL, This->src_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3668 }
3669
3670 static HRESULT WINAPI MLangConvertCharset_DoConversionFromUnicode(IMLangConvertCharset *iface,
3671 WCHAR *src, UINT *src_size, CHAR *dest, UINT *dest_size)
3672 {
3673 struct convert_charset *This = impl_from_IMLangConvertCharset(iface);
3674 TRACE("(%p)->(%p %p %p %p)\n", This, src, src_size, dest, dest_size);
3675 return ConvertINetUnicodeToMultiByte(NULL, This->dst_cp, src, (INT*)src_size, dest, (INT*)dest_size);
3676 }
3677
3678 static const IMLangConvertCharsetVtbl MLangConvertCharsetVtbl =
3679 {
3680 MLangConvertCharset_QueryInterface,
3681 MLangConvertCharset_AddRef,
3682 MLangConvertCharset_Release,
3683 MLangConvertCharset_Initialize,
3684 MLangConvertCharset_GetSourceCodePage,
3685 MLangConvertCharset_GetDestinationCodePage,
3686 MLangConvertCharset_GetProperty,
3687 MLangConvertCharset_DoConversion,
3688 MLangConvertCharset_DoConversionToUnicode,
3689 MLangConvertCharset_DoConversionFromUnicode
3690 };
3691
3692 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3693 {
3694 MLang_impl *mlang;
3695 UINT i;
3696
3697 TRACE("Creating MultiLanguage object\n");
3698
3699 if( pUnkOuter )
3700 return CLASS_E_NOAGGREGATION;
3701
3702 mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
3703 mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
3704 mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
3705 mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
3706 mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
3707 mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
3708
3709 mlang->total_cp = 0;
3710 for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
3711 mlang->total_cp += mlang_data[i].number_of_cp;
3712
3713 /* do not enumerate unicode flavours */
3714 mlang->total_scripts = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
3715
3716 mlang->ref = 1;
3717 *ppObj = &mlang->IMultiLanguage_iface;
3718 TRACE("returning %p\n", mlang);
3719
3720 LockModule();
3721
3722 return S_OK;
3723 }
3724
3725 static HRESULT MLangConvertCharset_create(IUnknown *outer, void **obj)
3726 {
3727 struct convert_charset *convert;
3728
3729 if (outer)
3730 return CLASS_E_NOAGGREGATION;
3731
3732 *obj = NULL;
3733
3734 convert = HeapAlloc(GetProcessHeap(), 0, sizeof(struct convert_charset));
3735 if (!convert) return E_OUTOFMEMORY;
3736
3737 convert->IMLangConvertCharset_iface.lpVtbl = &MLangConvertCharsetVtbl;
3738 convert->ref = 1;
3739
3740 *obj = &convert->IMLangConvertCharset_iface;
3741
3742 LockModule();
3743
3744 return S_OK;
3745 }
3746
3747 /******************************************************************************/
3748
3749 HRESULT WINAPI DllCanUnloadNow(void)
3750 {
3751 return dll_count == 0 ? S_OK : S_FALSE;
3752 }
3753
3754
3755 /***********************************************************************
3756 * DllRegisterServer (MLANG.@)
3757 */
3758 HRESULT WINAPI DllRegisterServer(void)
3759 {
3760 return __wine_register_resources( instance );
3761 }
3762
3763 /***********************************************************************
3764 * DllUnregisterServer (MLANG.@)
3765 */
3766 HRESULT WINAPI DllUnregisterServer(void)
3767 {
3768 return __wine_unregister_resources( instance );
3769 }
3770
3771 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
3772 {
3773 if (!unknown) return E_INVALIDARG;
3774
3775 FIXME("%p: stub\n", unknown);
3776
3777 return S_FALSE;
3778 }