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