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