ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mlang.c
Go to the documentation of this file.
00001 /*
00002  *    MLANG Class Factory
00003  *
00004  * Copyright 2002 Lionel Ulmer
00005  * Copyright 2003,2004 Mike McCormack
00006  * Copyright 2004,2005 Dmitry Timoshkov
00007  * Copyright 2009 Detlef Riekenberg
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include "config.h"
00025 
00026 #include <stdarg.h>
00027 #include <stdio.h>
00028 
00029 #define COBJMACROS
00030 
00031 #include "windef.h"
00032 #include "winbase.h"
00033 #include "wingdi.h"
00034 #include "winuser.h"
00035 #include "ole2.h"
00036 #include "objbase.h"
00037 #include "rpcproxy.h"
00038 #include "mlang.h"
00039 
00040 #include "wine/unicode.h"
00041 #include "wine/debug.h"
00042 
00043 WINE_DEFAULT_DEBUG_CHANNEL(mlang);
00044 
00045 #include "initguid.h"
00046 
00047 #define CP_UNICODE 1200
00048 
00049 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj);
00050 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum);
00051 
00052 static HINSTANCE instance;
00053 static DWORD MLANG_tls_index; /* to store various per thead data */
00054 
00055 /* FIXME:
00056  * Under what circumstances HKEY_CLASSES_ROOT\MIME\Database\Codepage and
00057  * HKEY_CLASSES_ROOT\MIME\Database\Charset are used?
00058  */
00059 
00060 typedef struct
00061 {
00062     const char *description;
00063     UINT cp;
00064     DWORD flags;
00065     const char *web_charset;
00066     const char *header_charset;
00067     const char *body_charset;
00068 } MIME_CP_INFO;
00069 
00070 /* These data are based on the codepage info in libs/unicode/cpmap.pl */
00071 /* FIXME: Add 28604 (Celtic), 28606 (Balkan) */
00072 
00073 static const MIME_CP_INFO arabic_cp[] =
00074 {
00075     { "Arabic (864)",
00076       864, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00077            MIMECONTF_MIME_LATEST,
00078       "ibm864", "ibm864", "ibm864" },
00079     { "Arabic (1006)",
00080       1006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00081             MIMECONTF_MIME_LATEST,
00082       "ibm1006", "ibm1006", "ibm1006" },
00083     { "Arabic (Windows)",
00084       1256, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00085             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00086             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00087       "windows-1256", "windows-1256", "windows-1256" },
00088     { "Arabic (ISO)",
00089       28596, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00090              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00091              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00092              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00093       "iso-8859-6", "iso-8859-6", "iso-8859-6" }
00094 };
00095 static const MIME_CP_INFO baltic_cp[] =
00096 {
00097     { "Baltic (DOS)",
00098       775, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00099            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00100       "ibm775", "ibm775", "ibm775" },
00101     { "Baltic (Windows)",
00102       1257, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00103             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00104             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
00105             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00106       "windows-1257", "windows-1257", "windows-1257" },
00107     { "Baltic (ISO)",
00108       28594, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00109              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00110              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
00111              MIMECONTF_MIME_LATEST,
00112       "iso-8859-4", "iso-8859-4", "iso-8859-4" },
00113     { "Estonian (ISO)",
00114       28603, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00115              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00116       "iso-8859-13", "iso-8859-13", "iso-8859-13" }
00117 };
00118 static const MIME_CP_INFO chinese_simplified_cp[] =
00119 {
00120     { "Chinese Simplified (GB2312)",
00121       936, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00122            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00123            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00124            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00125       "gb2312", "gb2312", "gb2312" }
00126 };
00127 static const MIME_CP_INFO chinese_traditional_cp[] =
00128 {
00129     { "Chinese Traditional (Big5)",
00130       950, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00131            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00132            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00133            MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00134       "big5", "big5", "big5" }
00135 };
00136 static const MIME_CP_INFO central_european_cp[] =
00137 {
00138     { "Central European (DOS)",
00139       852, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
00140            MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
00141            MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00142       "ibm852", "ibm852", "ibm852" },
00143     { "Central European (Windows)",
00144       1250, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00145             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00146             MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
00147             MIMECONTF_MIME_LATEST,
00148       "windows-1250", "windows-1250", "windows-1250" },
00149     { "Central European (Mac)",
00150       10029, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00151              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00152       "x-mac-ce", "x-mac-ce", "x-mac-ce" },
00153     { "Central European (ISO)",
00154       28592, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00155              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00156              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
00157              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00158       "iso-8859-2", "iso-8859-2", "iso-8859-2" }
00159 };
00160 static const MIME_CP_INFO cyrillic_cp[] =
00161 {
00162     { "OEM Cyrillic",
00163       855, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00164            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00165       "ibm855", "ibm855", "ibm855" },
00166     { "Cyrillic (DOS)",
00167       866, MIMECONTF_BROWSER | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_BROWSER |
00168            MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
00169            MIMECONTF_MIME_LATEST,
00170       "cp866", "cp866", "cp866" },
00171 #if 0 /* Windows has 20866 as an official code page for KOI8-R */
00172     { "Cyrillic (KOI8-R)",
00173       878, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00174            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00175       "koi8-r", "koi8-r", "koi8-r" },
00176 #endif
00177     { "Cyrillic (Windows)",
00178       1251, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00179             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00180             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00181       "windows-1251", "windows-1251", "windows-1251" },
00182     { "Cyrillic (Mac)",
00183       10007, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00184              MIMECONTF_MIME_LATEST,
00185       "x-mac-cyrillic", "x-mac-cyrillic", "x-mac-cyrillic" },
00186     { "Cyrillic (KOI8-R)",
00187       20866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00188              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00189              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00190              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00191       "koi8-r", "koi8-r", "koi8-r" },
00192     { "Cyrillic (KOI8-U)",
00193       21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00194              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00195              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00196              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00197       "koi8-u", "koi8-u", "koi8-u" },
00198     { "Cyrillic (ISO)",
00199       28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00200              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00201              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00202              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00203       "iso-8859-5", "iso-8859-5", "iso-8859-5" }
00204 };
00205 static const MIME_CP_INFO greek_cp[] =
00206 {
00207     { "Greek (DOS)",
00208       737, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00209            MIMECONTF_MIME_LATEST,
00210       "ibm737", "ibm737", "ibm737" },
00211     { "Greek, Modern (DOS)",
00212       869, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00213            MIMECONTF_MIME_LATEST,
00214       "ibm869", "ibm869", "ibm869" },
00215     { "IBM EBCDIC (Greek Modern)",
00216       875, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00217            MIMECONTF_MIME_LATEST,
00218       "cp875", "cp875", "cp875" },
00219     { "Greek (Windows)",
00220       1253, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00221             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00222             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00223       "windows-1253", "windows-1253", "windows-1253" },
00224     { "Greek (Mac)",
00225       10006, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00226              MIMECONTF_MIME_LATEST,
00227       "x-mac-greek", "x-mac-greek", "x-mac-greek" },
00228     { "Greek (ISO)",
00229       28597, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00230              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00231              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00232              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00233       "iso-8859-7", "iso-8859-7", "iso-8859-7" }
00234 };
00235 static const MIME_CP_INFO hebrew_cp[] =
00236 {
00237     { "Hebrew (424)",
00238       424, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00239            MIMECONTF_MIME_LATEST,
00240       "ibm424", "ibm424", "ibm424" },
00241     { "Hebrew (856)",
00242       856, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00243            MIMECONTF_MIME_LATEST,
00244       "cp856", "cp856", "cp856" },
00245     { "Hebrew (DOS)",
00246       862, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
00247            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00248            MIMECONTF_MIME_LATEST,
00249       "dos-862", "dos-862", "dos-862" },
00250     { "Hebrew (Windows)",
00251       1255, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00252             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00253             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00254       "windows-1255", "windows-1255", "windows-1255" },
00255     { "Hebrew (ISO-Visual)",
00256       28598, MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
00257              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00258              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00259       "iso-8859-8", "iso-8859-8", "iso-8859-8" }
00260 };
00261 static const MIME_CP_INFO japanese_cp[] =
00262 {
00263     { "Japanese (Auto-Select)",
00264       50932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00265              MIMECONTF_IMPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
00266              MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00267       "_autodetect", "_autodetect", "_autodetect" },
00268     { "Japanese (EUC)",
00269       51932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00270              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00271              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
00272              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00273       "euc-jp", "euc-jp", "euc-jp" },
00274     { "Japanese (JIS)",
00275       50220, MIMECONTF_IMPORT | MIMECONTF_MAILNEWS | MIMECONTF_EXPORT |
00276              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
00277              MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST |
00278              MIMECONTF_MIME_IE4,
00279       "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
00280     { "Japanese (JIS 0208-1990 and 0212-1990)",
00281       20932, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00282              MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
00283       "EUC-JP","EUC-JP","EUC-JP"},
00284     { "Japanese (JIS-Allow 1 byte Kana)",
00285       50221, MIMECONTF_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_SAVABLE_BROWSER |
00286              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID_NLS |
00287              MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
00288       "csISO2022JP","iso-2022-jp","iso-2022-jp"},
00289     { "Japanese (JIS-Allow 1 byte Kana - SO/SI)",
00290       50222, MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_VALID |
00291              MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
00292       "iso-2022-jp","iso-2022-jp","iso-2022-jp"},
00293     { "Japanese (Mac)",
00294       10001, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00295              MIMECONTF_VALID | MIMECONTF_PRIVCONVERTER | MIMECONTF_MIME_LATEST,
00296       "x-mac-japanese","x-mac-japanese","x-mac-japanese"},
00297     { "Japanese (Shift-JIS)",
00298       932, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00299            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00300            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
00301            MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00302       "shift_jis", "iso-2022-jp", "iso-2022-jp" }
00303 };
00304 static const MIME_CP_INFO korean_cp[] =
00305 {
00306     { "Korean",
00307       949, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00308            MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00309            MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS |
00310            MIMECONTF_MIME_LATEST,
00311       "ks_c_5601-1987", "ks_c_5601-1987", "ks_c_5601-1987" }
00312 };
00313 static const MIME_CP_INFO thai_cp[] =
00314 {
00315     { "Thai (Windows)",
00316       874, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_MIME_LATEST,
00317       "ibm-thai", "ibm-thai", "ibm-thai" }
00318 };
00319 static const MIME_CP_INFO turkish_cp[] =
00320 {
00321     { "Turkish (DOS)",
00322       857, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00323            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00324       "ibm857", "ibm857", "ibm857" },
00325     { "IBM EBCDIC (Turkish Latin-5)",
00326       1026, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00327             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00328       "ibm1026", "ibm1026", "ibm1026" },
00329     { "Turkish (Windows)",
00330       1254, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00331             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00332             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
00333             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00334       "windows-1254", "windows-1254", "windows-1254" },
00335     { "Turkish (Mac)",
00336       10081, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00337              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00338       "x-mac-turkish", "x-mac-turkish", "x-mac-turkish" },
00339     { "Latin 3 (ISO)",
00340       28593, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
00341              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
00342              MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00343       "iso-8859-3", "iso-8859-3", "iso-8859-3" },
00344     { "Turkish (ISO)",
00345       28599, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00346              MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00347              MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
00348              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00349       "iso-8859-9", "iso-8859-9", "iso-8859-9" }
00350 };
00351 static const MIME_CP_INFO vietnamese_cp[] =
00352 {
00353     { "Vietnamese (Windows)",
00354       1258, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00355             MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00356             MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
00357             MIMECONTF_MIME_LATEST,
00358       "windows-1258", "windows-1258", "windows-1258" }
00359 };
00360 static const MIME_CP_INFO western_cp[] =
00361 {
00362     { "IBM EBCDIC (US-Canada)",
00363       37, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00364           MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00365       "ibm037", "ibm037", "ibm037" },
00366     { "OEM United States",
00367       437, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00368            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00369       "ibm437", "ibm437", "ibm437" },
00370     { "IBM EBCDIC (International)",
00371       500, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00372            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00373       "ibm500", "ibm500", "ibm500" },
00374     { "Western European (DOS)",
00375       850, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00376            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00377       "ibm850", "ibm850", "ibm850" },
00378     { "Portuguese (DOS)",
00379       860, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00380            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00381       "ibm860", "ibm860", "ibm860" },
00382     { "Icelandic (DOS)",
00383       861, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00384            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00385       "ibm861", "ibm861", "ibm861" },
00386     { "French Canadian (DOS)",
00387       863, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00388            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00389       "ibm863", "ibm863", "ibm863" },
00390     { "Nordic (DOS)",
00391       865, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00392            MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00393       "ibm865", "ibm865", "ibm865" },
00394     { "Western European (Windows)",
00395       1252, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL |
00396             MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS |
00397             MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID |
00398             MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00399       "windows-1252", "windows-1252", "iso-8859-1" },
00400     { "Western European (Mac)",
00401       10000, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00402              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00403       "macintosh", "macintosh", "macintosh" },
00404     { "Icelandic (Mac)",
00405       10079, MIMECONTF_IMPORT | MIMECONTF_EXPORT | MIMECONTF_VALID |
00406              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00407       "x-mac-icelandic", "x-mac-icelandic", "x-mac-icelandic" },
00408     { "US-ASCII",
00409       20127, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT | MIMECONTF_EXPORT |
00410              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_VALID |
00411              MIMECONTF_VALID_NLS | MIMECONTF_MIME_LATEST,
00412       "us-ascii", "us-ascii", "us-ascii" },
00413     { "Western European (ISO)",
00414       28591, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00415              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00416              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
00417              MIMECONTF_MIME_LATEST,
00418       "iso-8859-1", "iso-8859-1", "iso-8859-1" },
00419     { "Latin 9 (ISO)",
00420       28605, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
00421              MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00422              MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
00423              MIMECONTF_MIME_LATEST,
00424       "iso-8859-15", "iso-8859-15", "iso-8859-15" }
00425 };
00426 static const MIME_CP_INFO unicode_cp[] =
00427 {
00428     { "Unicode",
00429       CP_UNICODE, MIMECONTF_MINIMAL | MIMECONTF_IMPORT |
00430                   MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT |
00431                   MIMECONTF_VALID | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 |
00432                   MIMECONTF_MIME_LATEST,
00433       "unicode", "unicode", "unicode" },
00434     { "Unicode (UTF-7)",
00435       CP_UTF7, MIMECONTF_MAILNEWS | MIMECONTF_IMPORT |
00436                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_EXPORT | MIMECONTF_VALID |
00437                MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00438       "utf-7", "utf-7", "utf-7" },
00439     { "Unicode (UTF-8)",
00440       CP_UTF8, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_IMPORT |
00441                MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER |
00442                MIMECONTF_EXPORT | MIMECONTF_VALID | MIMECONTF_VALID_NLS |
00443                MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST,
00444       "utf-8", "utf-8", "utf-8" }
00445 };
00446 
00447 static const struct mlang_data
00448 {
00449     const char *description;
00450     UINT family_codepage;
00451     UINT number_of_cp;
00452     const MIME_CP_INFO *mime_cp_info;
00453     const char *fixed_font;
00454     const char *proportional_font;
00455     SCRIPT_ID sid;
00456 } mlang_data[] =
00457 {
00458     { "Arabic",1256,sizeof(arabic_cp)/sizeof(arabic_cp[0]),arabic_cp,
00459       "Courier","Arial", sidArabic }, /* FIXME */
00460     { "Baltic",1257,sizeof(baltic_cp)/sizeof(baltic_cp[0]),baltic_cp,
00461       "Courier","Arial", sidAsciiLatin }, /* FIXME */
00462     { "Chinese Simplified",936,sizeof(chinese_simplified_cp)/sizeof(chinese_simplified_cp[0]),chinese_simplified_cp,
00463       "Courier","Arial", sidHan }, /* FIXME */
00464     { "Chinese Traditional",950,sizeof(chinese_traditional_cp)/sizeof(chinese_traditional_cp[0]),chinese_traditional_cp,
00465       "Courier","Arial", sidBopomofo }, /* FIXME */
00466     { "Central European",1250,sizeof(central_european_cp)/sizeof(central_european_cp[0]),central_european_cp,
00467       "Courier","Arial", sidAsciiLatin }, /* FIXME */
00468     { "Cyrillic",1251,sizeof(cyrillic_cp)/sizeof(cyrillic_cp[0]),cyrillic_cp,
00469       "Courier","Arial", sidCyrillic }, /* FIXME */
00470     { "Greek",1253,sizeof(greek_cp)/sizeof(greek_cp[0]),greek_cp,
00471       "Courier","Arial", sidGreek }, /* FIXME */
00472     { "Hebrew",1255,sizeof(hebrew_cp)/sizeof(hebrew_cp[0]),hebrew_cp,
00473       "Courier","Arial", sidHebrew }, /* FIXME */
00474     { "Japanese",932,sizeof(japanese_cp)/sizeof(japanese_cp[0]),japanese_cp,
00475       "MS Gothic","MS PGothic", sidKana },
00476     { "Korean",949,sizeof(korean_cp)/sizeof(korean_cp[0]),korean_cp,
00477       "Courier","Arial", sidHangul }, /* FIXME */
00478     { "Thai",874,sizeof(thai_cp)/sizeof(thai_cp[0]),thai_cp,
00479       "Courier","Arial", sidThai }, /* FIXME */
00480     { "Turkish",1254,sizeof(turkish_cp)/sizeof(turkish_cp[0]),turkish_cp,
00481       "Courier","Arial", sidAsciiLatin }, /* FIXME */
00482     { "Vietnamese",1258,sizeof(vietnamese_cp)/sizeof(vietnamese_cp[0]),vietnamese_cp,
00483       "Courier","Arial", sidAsciiLatin }, /* FIXME */
00484     { "Western European",1252,sizeof(western_cp)/sizeof(western_cp[0]),western_cp,
00485       "Courier","Arial", sidAsciiLatin }, /* FIXME */
00486     { "Unicode",CP_UNICODE,sizeof(unicode_cp)/sizeof(unicode_cp[0]),unicode_cp,
00487       "Courier","Arial" } /* FIXME */
00488 };
00489 
00490 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
00491 
00492 static LONG dll_count;
00493 
00494 /*
00495  * Japanese Detection and Converstion Functions
00496  */
00497 
00498 #define HANKATA(A)  ((A >= 161) && (A <= 223))
00499 #define ISEUC(A)    ((A >= 161) && (A <= 254))
00500 #define NOTEUC(A,B) (((A >= 129) && (A <= 159)) && ((B >= 64) && (B <= 160)))
00501 #define SJIS1(A)    (((A >= 129) && (A <= 159)) || ((A >= 224) && (A <= 239)))
00502 #define SJIS2(A)    ((A >= 64) && (A <= 252))
00503 #define ISMARU(A)   ((A >= 202) && (A <= 206))
00504 #define ISNIGORI(A) (((A >= 182) && (A <= 196)) || ((A >= 202) && (A <= 206)))
00505 
00506 static UINT DetectJapaneseCode(LPCSTR input, DWORD count)
00507 {
00508     UINT code = 0;
00509     DWORD i = 0;
00510     unsigned char c1,c2;
00511 
00512     while ((code == 0 || code == 51932) && i < count)
00513     {
00514         c1 = input[i];
00515         if (c1 == 0x1b /* ESC */)
00516         {
00517             i++;
00518             if (i >= count)
00519                 return code;
00520             c1 = input[i];
00521             if (c1 == '$')
00522             {
00523                 i++;
00524                 if (i >= count)
00525                     return code;
00526                 c1 = input[i];
00527                 if (c1 =='B' || c1 == '@')
00528                     code = 50220;
00529             }
00530             if (c1 == 'K')
00531                 code = 50220;
00532         }
00533         else if (c1 >= 129)
00534         {
00535             i++;
00536             if (i >= count)
00537                 return code;
00538             c2 = input[i];
00539             if NOTEUC(c1,c2)
00540                 code = 932;
00541             else if (ISEUC(c1) && ISEUC(c2))
00542                 code = 51932;
00543             else if (((c1 == 142)) && HANKATA(c2))
00544                 code = 51932;
00545         }
00546         i++;
00547     }
00548     return code;
00549 }
00550 
00551 static inline void jis2sjis(unsigned char *p1, unsigned char *p2)
00552 {
00553     unsigned char c1 = *p1;
00554     unsigned char c2 = *p2;
00555     int row = c1 < 95 ? 112 : 176;
00556     int cell = c1 % 2 ? 31 + (c2 > 95) : 126;
00557 
00558     *p1 = ((c1 + 1) >> 1) + row;
00559     *p2 = c2 + cell;
00560 }
00561 
00562 static inline void sjis2jis(unsigned char *p1, unsigned char *p2)
00563 {
00564     unsigned char c1 = *p1;
00565     unsigned char c2 = *p2;
00566     int shift = c2 < 159;
00567     int row = c1 < 160 ? 112 : 176;
00568     int cell = shift ? (31 + (c2 > 127)): 126;
00569 
00570     *p1 = ((c1 - row) << 1) - shift;
00571     *p2 -= cell;
00572 }
00573 
00574 static int han2zen(unsigned char *p1, unsigned char *p2)
00575 {
00576     int maru = FALSE;
00577     int nigori = FALSE;
00578     static const unsigned char char1[] = {129,129,129,129,129,131,131,131,131,
00579         131,131,131,131,131,131,129,131,131,131,131,131,131,131,131,131,131,
00580         131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
00581         131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
00582         131,129,129 };
00583     static const unsigned char char2[] = {66,117,118,65,69,146,64,66,68,70,
00584         72,131,133,135,98,91,65,67,69,71,73,74,76,78,80,82,84,86,88,90,92,94,
00585         96,99,101,103,105,106,107,108,109,110,113,116,119,122,125,126,128,
00586         129,130,132,134,136,137,138,139,140,141,143,147,74,75};
00587 
00588     if (( *p2 == 222) && ((ISNIGORI(*p1) || (*p1 == 179))))
00589             nigori = TRUE;
00590     else if ((*p2 == 223) && (ISMARU(*p1)))
00591             maru = TRUE;
00592 
00593     if (*p1 >= 161 && *p1 <= 223)
00594     {
00595         unsigned char index = *p1 - 161;
00596         *p1 = char1[index];
00597         *p2 = char2[index];
00598     }
00599 
00600     if (maru || nigori)
00601     {
00602         if (nigori)
00603         {
00604             if (((*p2 >= 74) && (*p2 <= 103)) || ((*p2 >= 110) && (*p2 <= 122)))
00605                 (*p2)++;
00606             else if ((*p1 == 131) && (*p2 == 69))
00607                 *p2 = 148;
00608         }
00609         else if ((maru) && ((*p2 >= 110) && (*p2 <= 122)))
00610             *p2+= 2;
00611 
00612         return 1;
00613     }
00614 
00615     return 0;
00616 }
00617 
00618 
00619 static UINT ConvertJIS2SJIS(LPCSTR input, DWORD count, LPSTR output)
00620 {
00621     DWORD i = 0;
00622     int j = 0;
00623     unsigned char p2,p;
00624     int shifted = FALSE;
00625 
00626     while (i < count)
00627     {
00628         p = input[i];
00629         if (p == 0x1b /* ESC */)
00630         {
00631             i++;
00632             if (i >= count)
00633                 return 0;
00634             p2 = input[i];
00635             if (p2 == '$' || p2 =='(')
00636                 i++;
00637             if (p2 == 'K' || p2 =='$')
00638                 shifted = TRUE;
00639             else
00640                 shifted = FALSE;
00641         }
00642         else
00643         {
00644             if (shifted)
00645             {
00646                 i++;
00647                 if (i >= count)
00648                     return 0;
00649                 p2 = input[i];
00650                 jis2sjis(&p,&p2);
00651                 output[j++]=p;
00652                 output[j++]=p2;
00653             }
00654             else
00655             {
00656                 output[j++] = p;
00657             }
00658         }
00659         i++;
00660     }
00661     return j;
00662 }
00663 
00664 static inline int exit_shift(LPSTR out, int c)
00665 {
00666     if (out)
00667     {
00668         out[c] = 0x1b;
00669         out[c+1] = '(';
00670         out[c+2] = 'B';
00671     }
00672     return 3;
00673 }
00674 
00675 static inline int enter_shift(LPSTR out, int c)
00676 {
00677     if (out)
00678     {
00679         out[c] = 0x1b;
00680         out[c+1] = '$';
00681         out[c+2] = 'B';
00682     }
00683     return 3;
00684 }
00685 
00686 
00687 static UINT ConvertSJIS2JIS(LPCSTR input, DWORD count, LPSTR output)
00688 {
00689     DWORD i = 0;
00690     int j = 0;
00691     unsigned char p2,p;
00692     int shifted = FALSE;
00693 
00694     while (i < count)
00695     {
00696         p = input[i] & 0xff;
00697         if (p == 10 || p == 13) /* NL and CR */
00698         {
00699             if (shifted)
00700             {
00701                 shifted = FALSE;
00702                 j += exit_shift(output,j);
00703             }
00704             if (output)
00705                 output[j++] = p;
00706             else
00707                 j++;
00708         }
00709         else
00710         {
00711             if (SJIS1(p))
00712             {
00713                 i++;
00714                 if (i >= count)
00715                     return 0;
00716                 p2 = input[i] & 0xff;
00717                 if (SJIS2(p2))
00718                 {
00719                     sjis2jis(&p,&p2);
00720                     if (!shifted)
00721                     {
00722                         shifted = TRUE;
00723                         j+=enter_shift(output,j);
00724                     }
00725                 }
00726 
00727                 if (output)
00728                 {
00729                     output[j++]=p;
00730                     output[j++]=p2;
00731                 }
00732                 else
00733                     j+=2;
00734             }
00735             else
00736             {
00737                 if (HANKATA(p))
00738                 {
00739                     if ((i+1) >= count)
00740                         return 0;
00741                     p2 = input[i+1] & 0xff;
00742                     i+=han2zen(&p,&p2);
00743                     sjis2jis(&p,&p2);
00744                     if (!shifted)
00745                     {
00746                         shifted = TRUE;
00747                         j+=enter_shift(output,j);
00748                     }
00749                     if (output)
00750                     {
00751                         output[j++]=p;
00752                         output[j++]=p2;
00753                     }
00754                     else
00755                         j+=2;
00756                 }
00757                 else
00758                 {
00759                     if (shifted)
00760                     {
00761                         shifted = FALSE;
00762                         j += exit_shift(output,j);
00763                     }
00764                     if (output)
00765                         output[j++]=p;
00766                     else
00767                         j++;
00768                 }
00769             }
00770         }
00771         i++;
00772     }
00773     if (shifted)
00774         j += exit_shift(output,j);
00775     return j;
00776 }
00777 
00778 static UINT ConvertJISJapaneseToUnicode(LPCSTR input, DWORD count,
00779                                         LPWSTR output, DWORD out_count)
00780 {
00781     CHAR *sjis_string;
00782     UINT rc = 0;
00783     sjis_string = HeapAlloc(GetProcessHeap(),0,count);
00784     rc = ConvertJIS2SJIS(input,count,sjis_string);
00785     if (rc)
00786     {
00787         TRACE("%s\n",debugstr_an(sjis_string,rc));
00788         if (output)
00789             rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
00790         else
00791             rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
00792     }
00793     HeapFree(GetProcessHeap(),0,sjis_string);
00794     return rc;
00795 
00796 }
00797 
00798 static UINT ConvertUnknownJapaneseToUnicode(LPCSTR input, DWORD count,
00799                                             LPWSTR output, DWORD out_count)
00800 {
00801     CHAR *sjis_string;
00802     UINT rc = 0;
00803     int code = DetectJapaneseCode(input,count);
00804     TRACE("Japanese code %i\n",code);
00805 
00806     switch (code)
00807     {
00808     case 0:
00809         if (output)
00810             rc = MultiByteToWideChar(CP_ACP,0,input,count,output,out_count);
00811         else
00812             rc = MultiByteToWideChar(CP_ACP,0,input,count,0,0);
00813         break;
00814 
00815     case 932:
00816         if (output)
00817             rc = MultiByteToWideChar(932,0,input,count,output,out_count);
00818         else
00819             rc = MultiByteToWideChar(932,0,input,count,0,0);
00820         break;
00821 
00822     case 51932:
00823         if (output)
00824             rc = MultiByteToWideChar(20932,0,input,count,output,out_count);
00825         else
00826             rc = MultiByteToWideChar(20932,0,input,count,0,0);
00827         break;
00828 
00829     case 50220:
00830         sjis_string = HeapAlloc(GetProcessHeap(),0,count);
00831         rc = ConvertJIS2SJIS(input,count,sjis_string);
00832         if (rc)
00833         {
00834             TRACE("%s\n",debugstr_an(sjis_string,rc));
00835             if (output)
00836                 rc = MultiByteToWideChar(932,0,sjis_string,rc,output,out_count);
00837             else
00838                 rc = MultiByteToWideChar(932,0,sjis_string,rc,0,0);
00839         }
00840         HeapFree(GetProcessHeap(),0,sjis_string);
00841         break;
00842     }
00843     return rc;
00844 }
00845 
00846 static UINT ConvertJapaneseUnicodeToJIS(LPCWSTR input, DWORD count,
00847                                         LPSTR output, DWORD out_count)
00848 {
00849     CHAR *sjis_string;
00850     INT len;
00851     UINT rc = 0;
00852 
00853     len = WideCharToMultiByte(932,0,input,count,0,0,NULL,NULL);
00854     sjis_string = HeapAlloc(GetProcessHeap(),0,len);
00855     WideCharToMultiByte(932,0,input,count,sjis_string,len,NULL,NULL);
00856     TRACE("%s\n",debugstr_an(sjis_string,len));
00857 
00858     rc = ConvertSJIS2JIS(sjis_string, len, NULL);
00859     if (out_count >= rc)
00860     {
00861         ConvertSJIS2JIS(sjis_string, len, output);
00862     }
00863     HeapFree(GetProcessHeap(),0,sjis_string);
00864     return rc;
00865 
00866 }
00867 
00868 /*
00869  * Dll lifetime tracking declaration
00870  */
00871 static void LockModule(void)
00872 {
00873     InterlockedIncrement(&dll_count);
00874 }
00875 
00876 static void UnlockModule(void)
00877 {
00878     InterlockedDecrement(&dll_count);
00879 }
00880 
00881 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
00882 {
00883     switch(fdwReason) {
00884         case DLL_PROCESS_ATTACH:
00885             instance = hInstDLL;
00886             MLANG_tls_index = TlsAlloc();
00887             DisableThreadLibraryCalls(hInstDLL);
00888         break;
00889     case DLL_PROCESS_DETACH:
00890             TlsFree(MLANG_tls_index);
00891         break;
00892     }
00893     return TRUE;
00894 }
00895 
00896 HRESULT WINAPI ConvertINetMultiByteToUnicode(
00897     LPDWORD pdwMode,
00898     DWORD dwEncoding,
00899     LPCSTR pSrcStr,
00900     LPINT pcSrcSize,
00901     LPWSTR pDstStr,
00902     LPINT pcDstSize)
00903 {
00904     INT src_len = -1;
00905 
00906     TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
00907           debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
00908 
00909     if (!pcDstSize)
00910         return E_FAIL;
00911 
00912     if (!pcSrcSize)
00913         pcSrcSize = &src_len;
00914 
00915     if (!*pcSrcSize)
00916     {
00917         *pcDstSize = 0;
00918         return S_OK;
00919     }
00920 
00921     /* forwarding euc-jp to EUC-JP */
00922     if (dwEncoding == 51932)
00923         dwEncoding = 20932;
00924 
00925     switch (dwEncoding)
00926     {
00927     case CP_UNICODE:
00928         if (*pcSrcSize == -1)
00929             *pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
00930         *pcDstSize = min(*pcSrcSize, *pcDstSize);
00931         *pcSrcSize *= sizeof(WCHAR);
00932         if (pDstStr)
00933             memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
00934         break;
00935 
00936     case 50220:
00937     case 50221:
00938     case 50222:
00939         *pcDstSize = ConvertJISJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
00940         break;
00941     case 50932:
00942         *pcDstSize = ConvertUnknownJapaneseToUnicode(pSrcStr,*pcSrcSize,pDstStr,*pcDstSize);
00943         break;
00944 
00945     default:
00946         if (*pcSrcSize == -1)
00947             *pcSrcSize = lstrlenA(pSrcStr);
00948 
00949         if (pDstStr)
00950             *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
00951         else
00952             *pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
00953         break;
00954     }
00955     
00956     if (!*pcDstSize)
00957         return E_FAIL;
00958 
00959     return S_OK;
00960 }
00961 
00962 HRESULT WINAPI ConvertINetUnicodeToMultiByte(
00963     LPDWORD pdwMode,
00964     DWORD dwEncoding,
00965     LPCWSTR pSrcStr,
00966     LPINT pcSrcSize,
00967     LPSTR pDstStr,
00968     LPINT pcDstSize)
00969 {
00970     INT destsz, size;
00971     INT src_len = -1;
00972 
00973     TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
00974           debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
00975 
00976     if (!pcDstSize)
00977         return S_OK;
00978 
00979     if (!pcSrcSize)
00980         pcSrcSize = &src_len;
00981 
00982     destsz = (pDstStr) ? *pcDstSize : 0;
00983     *pcDstSize = 0;
00984 
00985     if (!pSrcStr || !*pcSrcSize)
00986         return S_OK;
00987 
00988     if (*pcSrcSize == -1)
00989         *pcSrcSize = lstrlenW(pSrcStr);
00990 
00991     /* forwarding euc-jp to EUC-JP */
00992     if (dwEncoding == 51932)
00993         dwEncoding = 20932;
00994 
00995     if (dwEncoding == CP_UNICODE)
00996     {
00997         if (*pcSrcSize == -1)
00998             *pcSrcSize = lstrlenW(pSrcStr);
00999 
01000         size = min(*pcSrcSize, destsz) * sizeof(WCHAR);
01001         if (pDstStr)
01002             memmove(pDstStr, pSrcStr, size);
01003 
01004         if (size >= destsz)
01005             goto fail;
01006     }
01007     else if (dwEncoding == 50220 || dwEncoding == 50221 || dwEncoding == 50222)
01008     {
01009         size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, NULL, 0);
01010         if (!size)
01011             goto fail;
01012 
01013         if (pDstStr)
01014         {
01015             size = ConvertJapaneseUnicodeToJIS(pSrcStr, *pcSrcSize, pDstStr,
01016                                                destsz);
01017             if (!size)
01018                 goto fail;
01019         }
01020 
01021     }
01022     else
01023     {
01024         size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
01025                                    NULL, 0, NULL, NULL);
01026         if (!size)
01027             goto fail;
01028 
01029         if (pDstStr)
01030         {
01031             size = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize,
01032                                        pDstStr, destsz, NULL, NULL);
01033             if (!size)
01034                 goto fail;
01035         }
01036     }
01037 
01038     *pcDstSize = size;
01039     return S_OK;
01040 
01041 fail:
01042     *pcSrcSize = 0;
01043     *pcDstSize = 0;
01044     return E_FAIL;
01045 }
01046 
01047 HRESULT WINAPI ConvertINetString(
01048     LPDWORD pdwMode,
01049     DWORD dwSrcEncoding,
01050     DWORD dwDstEncoding,
01051     LPCSTR pSrcStr,
01052     LPINT pcSrcSize,
01053     LPSTR pDstStr,
01054     LPINT pcDstSize
01055 )
01056 {
01057     TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
01058           debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
01059 
01060     if (dwSrcEncoding == CP_UNICODE)
01061     {
01062         INT cSrcSizeW;
01063         if (pcSrcSize && *pcSrcSize != -1)
01064         {
01065             cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
01066             pcSrcSize = &cSrcSizeW;
01067         }
01068         return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
01069     }
01070     else if (dwDstEncoding == CP_UNICODE)
01071     {
01072         HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
01073         *pcDstSize *= sizeof(WCHAR);
01074         return hr;
01075     }
01076     else
01077     {
01078         INT cDstSizeW;
01079         LPWSTR pDstStrW;
01080         HRESULT hr;
01081 
01082         TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
01083 
01084         hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
01085         if (hr != S_OK)
01086             return hr;
01087 
01088         pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
01089         hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
01090         if (hr == S_OK)
01091             hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
01092 
01093         HeapFree(GetProcessHeap(), 0, pDstStrW);
01094         return hr;
01095     }
01096 }
01097 
01098 static HRESULT GetFamilyCodePage(
01099     UINT uiCodePage,
01100     UINT* puiFamilyCodePage)
01101 {
01102     UINT i, n;
01103 
01104     TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
01105 
01106     if (!puiFamilyCodePage) return S_FALSE;
01107 
01108     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
01109     {
01110         for (n = 0; n < mlang_data[i].number_of_cp; n++)
01111         {
01112             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
01113             {
01114                 *puiFamilyCodePage = mlang_data[i].family_codepage;
01115                 return S_OK;
01116             }
01117         }
01118     }
01119 
01120     return S_FALSE;
01121 }
01122 
01123 HRESULT WINAPI IsConvertINetStringAvailable(
01124     DWORD dwSrcEncoding,
01125     DWORD dwDstEncoding)
01126 {
01127     UINT src_family, dst_family;
01128 
01129     TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
01130 
01131     if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
01132         GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
01133         return S_FALSE;
01134 
01135     if (src_family == dst_family) return S_OK;
01136 
01137     /* we can convert any codepage to/from unicode */
01138     if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
01139 
01140     return S_FALSE;
01141 }
01142 
01143 static inline HRESULT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
01144 {
01145     CHAR buffer[MAX_RFC1766_NAME];
01146     INT n = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
01147     INT i;
01148 
01149     if (n)
01150     {
01151         i = PRIMARYLANGID(lcid);
01152         if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
01153             (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
01154             (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
01155 
01156             buffer[n - 1] = '-';
01157             i = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
01158             if (!i)
01159                 buffer[n - 1] = '\0';
01160         }
01161         else
01162             i = 0;
01163 
01164         LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len );
01165         return ((n + i) > len) ? E_INVALIDARG : S_OK;
01166     }
01167     return E_FAIL;
01168 }
01169 
01170 static inline HRESULT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
01171 {
01172     WCHAR buffer[MAX_RFC1766_NAME];
01173     INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, MAX_RFC1766_NAME);
01174     INT i;
01175 
01176     if (n)
01177     {
01178         i = PRIMARYLANGID(lcid);
01179         if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
01180             (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
01181             (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
01182 
01183             buffer[n - 1] = '-';
01184             i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, MAX_RFC1766_NAME - n);
01185             if (!i)
01186                 buffer[n - 1] = '\0';
01187         }
01188         else
01189             i = 0;
01190 
01191         LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
01192         return ((n + i) > len) ? E_INVALIDARG : S_OK;
01193     }
01194     return E_FAIL;
01195 }
01196 
01197 HRESULT WINAPI LcidToRfc1766A(
01198     LCID lcid,
01199     LPSTR pszRfc1766,
01200     INT nChar)
01201 {
01202     TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
01203     if (!pszRfc1766)
01204         return E_INVALIDARG;
01205 
01206     return lcid_to_rfc1766A(lcid, pszRfc1766, nChar);
01207 }
01208 
01209 HRESULT WINAPI LcidToRfc1766W(
01210     LCID lcid,
01211     LPWSTR pszRfc1766,
01212     INT nChar)
01213 {
01214     TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
01215     if (!pszRfc1766)
01216         return E_INVALIDARG;
01217 
01218     return lcid_to_rfc1766W(lcid, pszRfc1766, nChar);
01219 }
01220 
01221 static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
01222 {
01223     RFC1766INFO info;
01224     ULONG num;
01225 
01226     while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
01227     {
01228         if (!strcmpiW(info.wszRfc1766, rfc1766))
01229         {
01230             *lcid = info.lcid;
01231             return S_OK;
01232         }
01233         if (strlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
01234         {
01235             *lcid = PRIMARYLANGID(info.lcid);
01236             return S_OK;
01237         }
01238     }
01239 
01240     return E_FAIL;
01241 }
01242 
01243 HRESULT WINAPI Rfc1766ToLcidW(LCID *pLocale, LPCWSTR pszRfc1766)
01244 {
01245     IEnumRfc1766 *enumrfc1766;
01246     HRESULT hr;
01247 
01248     TRACE("(%p, %s)\n", pLocale, debugstr_w(pszRfc1766));
01249 
01250     if (!pLocale || !pszRfc1766)
01251         return E_INVALIDARG;
01252 
01253     hr = EnumRfc1766_create(0, &enumrfc1766);
01254     if (FAILED(hr))
01255         return hr;
01256 
01257     hr = lcid_from_rfc1766(enumrfc1766, pLocale, pszRfc1766);
01258     IEnumRfc1766_Release(enumrfc1766);
01259 
01260     return hr;
01261 }
01262 
01263 HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
01264 {
01265     WCHAR rfc1766W[MAX_RFC1766_NAME + 1];
01266 
01267     if (!rfc1766A)
01268         return E_INVALIDARG;
01269 
01270     MultiByteToWideChar(CP_ACP, 0, rfc1766A, -1, rfc1766W, MAX_RFC1766_NAME);
01271     rfc1766W[MAX_RFC1766_NAME] = 0;
01272 
01273     return Rfc1766ToLcidW(lcid, rfc1766W);
01274 }
01275 
01276 /******************************************************************************
01277  * MLANG ClassFactory
01278  */
01279 typedef struct {
01280     IClassFactory ITF_IClassFactory;
01281 
01282     LONG ref;
01283     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
01284 } IClassFactoryImpl;
01285 
01286 struct object_creation_info
01287 {
01288     const CLSID *clsid;
01289     LPCSTR szClassName;
01290     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
01291 };
01292 
01293 static const struct object_creation_info object_creation[] =
01294 {
01295     { &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
01296 };
01297 
01298 static HRESULT WINAPI
01299 MLANGCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
01300 {
01301     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
01302 
01303     TRACE("%s\n", debugstr_guid(riid) );
01304 
01305     if (IsEqualGUID(riid, &IID_IUnknown)
01306     || IsEqualGUID(riid, &IID_IClassFactory))
01307     {
01308     IClassFactory_AddRef(iface);
01309     *ppobj = This;
01310     return S_OK;
01311     }
01312 
01313     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
01314     return E_NOINTERFACE;
01315 }
01316 
01317 static ULONG WINAPI MLANGCF_AddRef(LPCLASSFACTORY iface)
01318 {
01319     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
01320     return InterlockedIncrement(&This->ref);
01321 }
01322 
01323 static ULONG WINAPI MLANGCF_Release(LPCLASSFACTORY iface)
01324 {
01325     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
01326 
01327     ULONG ref = InterlockedDecrement(&This->ref);
01328 
01329     if (ref == 0)
01330     {
01331         TRACE("Destroying %p\n", This);
01332     HeapFree(GetProcessHeap(), 0, This);
01333     }
01334 
01335     return ref;
01336 }
01337 
01338 static HRESULT WINAPI MLANGCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
01339                       REFIID riid, LPVOID *ppobj)
01340 {
01341     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
01342     HRESULT hres;
01343     LPUNKNOWN punk;
01344     
01345     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
01346 
01347     *ppobj = NULL;
01348     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
01349     if (SUCCEEDED(hres)) {
01350         hres = IUnknown_QueryInterface(punk, riid, ppobj);
01351         IUnknown_Release(punk);
01352     }
01353     TRACE("returning (%p) -> %x\n", *ppobj, hres);
01354     return hres;
01355 }
01356 
01357 static HRESULT WINAPI MLANGCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
01358 {
01359     if (dolock)
01360         LockModule();
01361     else
01362         UnlockModule();
01363 
01364     return S_OK;
01365 }
01366 
01367 static const IClassFactoryVtbl MLANGCF_Vtbl =
01368 {
01369     MLANGCF_QueryInterface,
01370     MLANGCF_AddRef,
01371     MLANGCF_Release,
01372     MLANGCF_CreateInstance,
01373     MLANGCF_LockServer
01374 };
01375 
01376 /******************************************************************
01377  *      DllGetClassObject (MLANG.@)
01378  */
01379 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
01380 {
01381     unsigned int i;
01382     IClassFactoryImpl *factory;
01383 
01384     TRACE("%s %s %p\n",debugstr_guid(rclsid), debugstr_guid(iid), ppv);
01385 
01386     if ( !IsEqualGUID( &IID_IClassFactory, iid )
01387      && ! IsEqualGUID( &IID_IUnknown, iid) )
01388     return E_NOINTERFACE;
01389 
01390     for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
01391     {
01392     if (IsEqualGUID(object_creation[i].clsid, rclsid))
01393         break;
01394     }
01395 
01396     if (i == sizeof(object_creation)/sizeof(object_creation[0]))
01397     {
01398     FIXME("%s: no class found.\n", debugstr_guid(rclsid));
01399     return CLASS_E_CLASSNOTAVAILABLE;
01400     }
01401 
01402     TRACE("Creating a class factory for %s\n",object_creation[i].szClassName);
01403 
01404     factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
01405     if (factory == NULL) return E_OUTOFMEMORY;
01406 
01407     factory->ITF_IClassFactory.lpVtbl = &MLANGCF_Vtbl;
01408     factory->ref = 1;
01409 
01410     factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
01411 
01412     *ppv = &(factory->ITF_IClassFactory);
01413 
01414     TRACE("(%p) <- %p\n", ppv, &(factory->ITF_IClassFactory) );
01415 
01416     return S_OK;
01417 }
01418 
01419 
01420 /******************************************************************************/
01421 
01422 typedef struct tagMLang_impl
01423 {
01424     IMLangFontLink IMLangFontLink_iface;
01425     IMultiLanguage IMultiLanguage_iface;
01426     IMultiLanguage3 IMultiLanguage3_iface;
01427     IMLangFontLink2 IMLangFontLink2_iface;
01428     IMLangLineBreakConsole IMLangLineBreakConsole_iface;
01429     LONG ref;
01430     DWORD total_cp, total_scripts;
01431 } MLang_impl;
01432 
01433 static ULONG MLang_AddRef( MLang_impl* This)
01434 {
01435     return InterlockedIncrement(&This->ref);
01436 }
01437 
01438 static ULONG MLang_Release( MLang_impl* This )
01439 {
01440     ULONG ref = InterlockedDecrement(&This->ref);
01441 
01442     TRACE("%p ref = %d\n", This, ref);
01443     if (ref == 0)
01444     {
01445         TRACE("Destroying %p\n", This);
01446     HeapFree(GetProcessHeap(), 0, This);
01447         UnlockModule();
01448     }
01449 
01450     return ref;
01451 }
01452 
01453 static HRESULT MLang_QueryInterface(
01454         MLang_impl* This,
01455         REFIID riid,
01456         void** ppvObject)
01457 {
01458     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
01459 
01460     if (IsEqualGUID(riid, &IID_IUnknown)
01461     || IsEqualGUID(riid, &IID_IMLangCodePages)
01462     || IsEqualGUID(riid, &IID_IMLangFontLink))
01463     {
01464     MLang_AddRef(This);
01465         TRACE("Returning IID_IMLangFontLink %p ref = %d\n", This, This->ref);
01466     *ppvObject = &This->IMLangFontLink_iface;
01467     return S_OK;
01468     }
01469 
01470     if (IsEqualGUID(riid, &IID_IMLangFontLink2))
01471     {
01472     MLang_AddRef(This);
01473         TRACE("Returning IID_IMLangFontLink2 %p ref = %d\n", This, This->ref);
01474     *ppvObject = &This->IMLangFontLink2_iface;
01475     return S_OK;
01476     }
01477 
01478     if (IsEqualGUID(riid, &IID_IMultiLanguage) )
01479     {
01480     MLang_AddRef(This);
01481         TRACE("Returning IID_IMultiLanguage %p ref = %d\n", This, This->ref);
01482     *ppvObject = &This->IMultiLanguage_iface;
01483     return S_OK;
01484     }
01485 
01486     if (IsEqualGUID(riid, &IID_IMultiLanguage2) )
01487     {
01488     MLang_AddRef(This);
01489     *ppvObject = &This->IMultiLanguage3_iface;
01490         TRACE("Returning IID_IMultiLanguage2 %p ref = %d\n", This, This->ref);
01491     return S_OK;
01492     }
01493 
01494     if (IsEqualGUID(riid, &IID_IMultiLanguage3) )
01495     {
01496     MLang_AddRef(This);
01497     *ppvObject = &This->IMultiLanguage3_iface;
01498         TRACE("Returning IID_IMultiLanguage3 %p ref = %d\n", This, This->ref);
01499     return S_OK;
01500     }
01501 
01502     if (IsEqualGUID(riid, &IID_IMLangLineBreakConsole))
01503     {
01504     MLang_AddRef(This);
01505         TRACE("Returning IID_IMLangLineBreakConsole %p ref = %d\n", This, This->ref);
01506     *ppvObject = &This->IMLangLineBreakConsole_iface;
01507     return S_OK;
01508     }
01509 
01510 
01511     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
01512     return E_NOINTERFACE;
01513 }
01514 
01515 /******************************************************************************/
01516 
01517 typedef struct tagEnumCodePage_impl
01518 {
01519     IEnumCodePage IEnumCodePage_iface;
01520     LONG ref;
01521     MIMECPINFO *cpinfo;
01522     DWORD total, pos;
01523 } EnumCodePage_impl;
01524 
01525 static inline EnumCodePage_impl *impl_from_IEnumCodePage( IEnumCodePage *iface )
01526 {
01527     return CONTAINING_RECORD( iface, EnumCodePage_impl, IEnumCodePage_iface );
01528 }
01529 
01530 static HRESULT WINAPI fnIEnumCodePage_QueryInterface(
01531         IEnumCodePage* iface,
01532         REFIID riid,
01533         void** ppvObject)
01534 {
01535     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
01536 
01537     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
01538 
01539     if (IsEqualGUID(riid, &IID_IUnknown)
01540     || IsEqualGUID(riid, &IID_IEnumCodePage))
01541     {
01542     IEnumCodePage_AddRef(iface);
01543         TRACE("Returning IID_IEnumCodePage %p ref = %d\n", This, This->ref);
01544     *ppvObject = &This->IEnumCodePage_iface;
01545         return S_OK;
01546     }
01547 
01548     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
01549     return E_NOINTERFACE;
01550 }
01551 
01552 static ULONG WINAPI fnIEnumCodePage_AddRef(
01553         IEnumCodePage* iface)
01554 {
01555     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
01556     return InterlockedIncrement(&This->ref);
01557 }
01558 
01559 static ULONG WINAPI fnIEnumCodePage_Release(
01560         IEnumCodePage* iface)
01561 {
01562     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
01563     ULONG ref = InterlockedDecrement(&This->ref);
01564 
01565     TRACE("%p ref = %d\n", This, ref);
01566     if (ref == 0)
01567     {
01568         TRACE("Destroying %p\n", This);
01569         HeapFree(GetProcessHeap(), 0, This->cpinfo);
01570         HeapFree(GetProcessHeap(), 0, This);
01571     }
01572 
01573     return ref;
01574 }
01575 
01576 static HRESULT WINAPI fnIEnumCodePage_Clone(
01577         IEnumCodePage* iface,
01578         IEnumCodePage** ppEnum)
01579 {
01580     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
01581     FIXME("%p %p\n", This, ppEnum);
01582     return E_NOTIMPL;
01583 }
01584 
01585 static  HRESULT WINAPI fnIEnumCodePage_Next(
01586         IEnumCodePage* iface,
01587         ULONG celt,
01588         PMIMECPINFO rgelt,
01589         ULONG* pceltFetched)
01590 {
01591     ULONG i;
01592     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
01593 
01594     TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
01595 
01596     if (!pceltFetched) return S_FALSE;
01597     *pceltFetched = 0;
01598 
01599     if (!rgelt) return S_FALSE;
01600 
01601     if (This->pos + celt > This->total)
01602         celt = This->total - This->pos;
01603 
01604     if (!celt) return S_FALSE;
01605 
01606     memcpy(rgelt, This->cpinfo + This->pos, celt * sizeof(MIMECPINFO));
01607     *pceltFetched = celt;
01608     This->pos += celt;
01609 
01610     for (i = 0; i < celt; i++)
01611     {
01612         TRACE("#%u: %08x %u %u %s %s %s %s %s %s %d\n",
01613               i, rgelt[i].dwFlags, rgelt[i].uiCodePage,
01614               rgelt[i].uiFamilyCodePage,
01615               wine_dbgstr_w(rgelt[i].wszDescription),
01616               wine_dbgstr_w(rgelt[i].wszWebCharset),
01617               wine_dbgstr_w(rgelt[i].wszHeaderCharset),
01618               wine_dbgstr_w(rgelt[i].wszBodyCharset),
01619               wine_dbgstr_w(rgelt[i].wszFixedWidthFont),
01620               wine_dbgstr_w(rgelt[i].wszProportionalFont),
01621               rgelt[i].bGDICharset);
01622     }
01623     return S_OK;
01624 }
01625 
01626 static HRESULT WINAPI fnIEnumCodePage_Reset(
01627         IEnumCodePage* iface)
01628 {
01629     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
01630 
01631     TRACE("%p\n", This);
01632 
01633     This->pos = 0;
01634     return S_OK;
01635 }
01636 
01637 static  HRESULT WINAPI fnIEnumCodePage_Skip(
01638         IEnumCodePage* iface,
01639         ULONG celt)
01640 {
01641     EnumCodePage_impl *This = impl_from_IEnumCodePage( iface );
01642 
01643     TRACE("%p %u\n", This, celt);
01644 
01645     if (celt >= This->total) return S_FALSE;
01646 
01647     This->pos += celt;
01648     return S_OK;
01649 }
01650 
01651 static const IEnumCodePageVtbl IEnumCodePage_vtbl =
01652 {
01653     fnIEnumCodePage_QueryInterface,
01654     fnIEnumCodePage_AddRef,
01655     fnIEnumCodePage_Release,
01656     fnIEnumCodePage_Clone,
01657     fnIEnumCodePage_Next,
01658     fnIEnumCodePage_Reset,
01659     fnIEnumCodePage_Skip
01660 };
01661 
01662 static HRESULT EnumCodePage_create( MLang_impl* mlang, DWORD grfFlags,
01663                      LANGID LangId, IEnumCodePage** ppEnumCodePage )
01664 {
01665     EnumCodePage_impl *ecp;
01666     MIMECPINFO *cpinfo;
01667     UINT i, n;
01668 
01669     TRACE("%p, %08x, %04x, %p\n", mlang, grfFlags, LangId, ppEnumCodePage);
01670 
01671     if (!grfFlags) /* enumerate internal data base of encodings */
01672         grfFlags = MIMECONTF_MIME_LATEST;
01673 
01674     ecp = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumCodePage_impl) );
01675     ecp->IEnumCodePage_iface.lpVtbl = &IEnumCodePage_vtbl;
01676     ecp->ref = 1;
01677     ecp->pos = 0;
01678     ecp->total = 0;
01679     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
01680     {
01681         for (n = 0; n < mlang_data[i].number_of_cp; n++)
01682         {
01683             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
01684                 ecp->total++;
01685         }
01686     }
01687 
01688     ecp->cpinfo = HeapAlloc(GetProcessHeap(), 0,
01689                             sizeof(MIMECPINFO) * ecp->total);
01690     cpinfo = ecp->cpinfo;
01691 
01692     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
01693     {
01694         for (n = 0; n < mlang_data[i].number_of_cp; n++)
01695         {
01696             if (mlang_data[i].mime_cp_info[n].flags & grfFlags)
01697                 fill_cp_info(&mlang_data[i], n, cpinfo++);
01698         }
01699     }
01700 
01701     TRACE("enumerated %d codepages with flags %08x\n", ecp->total, grfFlags);
01702 
01703     *ppEnumCodePage = &ecp->IEnumCodePage_iface;
01704 
01705     return S_OK;
01706 }
01707 
01708 /******************************************************************************/
01709 
01710 typedef struct tagEnumScript_impl
01711 {
01712     IEnumScript IEnumScript_iface;
01713     LONG ref;
01714     SCRIPTINFO *script_info;
01715     DWORD total, pos;
01716 } EnumScript_impl;
01717 
01718 static inline EnumScript_impl *impl_from_IEnumScript( IEnumScript *iface )
01719 {
01720     return CONTAINING_RECORD( iface, EnumScript_impl, IEnumScript_iface );
01721 }
01722 
01723 static HRESULT WINAPI fnIEnumScript_QueryInterface(
01724         IEnumScript* iface,
01725         REFIID riid,
01726         void** ppvObject)
01727 {
01728     EnumScript_impl *This = impl_from_IEnumScript( iface );
01729 
01730     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
01731 
01732     if (IsEqualGUID(riid, &IID_IUnknown)
01733         || IsEqualGUID(riid, &IID_IEnumScript))
01734     {
01735         IEnumScript_AddRef(iface);
01736         TRACE("Returning IID_IEnumScript %p ref = %d\n", This, This->ref);
01737         *ppvObject = &This->IEnumScript_iface;
01738         return S_OK;
01739     }
01740 
01741     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
01742     return E_NOINTERFACE;
01743 }
01744 
01745 static ULONG WINAPI fnIEnumScript_AddRef(
01746         IEnumScript* iface)
01747 {
01748     EnumScript_impl *This = impl_from_IEnumScript( iface );
01749     return InterlockedIncrement(&This->ref);
01750 }
01751 
01752 static ULONG WINAPI fnIEnumScript_Release(
01753         IEnumScript* iface)
01754 {
01755     EnumScript_impl *This = impl_from_IEnumScript( iface );
01756     ULONG ref = InterlockedDecrement(&This->ref);
01757 
01758     TRACE("%p ref = %d\n", This, ref);
01759     if (ref == 0)
01760     {
01761         TRACE("Destroying %p\n", This);
01762         HeapFree(GetProcessHeap(), 0, This->script_info);
01763         HeapFree(GetProcessHeap(), 0, This);
01764     }
01765 
01766     return ref;
01767 }
01768 
01769 static HRESULT WINAPI fnIEnumScript_Clone(
01770         IEnumScript* iface,
01771         IEnumScript** ppEnum)
01772 {
01773     EnumScript_impl *This = impl_from_IEnumScript( iface );
01774     FIXME("%p %p: stub!\n", This, ppEnum);
01775     return E_NOTIMPL;
01776 }
01777 
01778 static  HRESULT WINAPI fnIEnumScript_Next(
01779         IEnumScript* iface,
01780         ULONG celt,
01781         PSCRIPTINFO rgelt,
01782         ULONG* pceltFetched)
01783 {
01784     EnumScript_impl *This = impl_from_IEnumScript( iface );
01785 
01786     TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
01787 
01788     if (!pceltFetched || !rgelt) return E_FAIL;
01789 
01790     *pceltFetched = 0;
01791 
01792     if (This->pos + celt > This->total)
01793         celt = This->total - This->pos;
01794 
01795     if (!celt) return S_FALSE;
01796 
01797     memcpy(rgelt, This->script_info + This->pos, celt * sizeof(SCRIPTINFO));
01798     *pceltFetched = celt;
01799     This->pos += celt;
01800 
01801     return S_OK;
01802 }
01803 
01804 static HRESULT WINAPI fnIEnumScript_Reset(
01805         IEnumScript* iface)
01806 {
01807     EnumScript_impl *This = impl_from_IEnumScript( iface );
01808 
01809     TRACE("%p\n", This);
01810 
01811     This->pos = 0;
01812     return S_OK;
01813 }
01814 
01815 static  HRESULT WINAPI fnIEnumScript_Skip(
01816         IEnumScript* iface,
01817         ULONG celt)
01818 {
01819     EnumScript_impl *This = impl_from_IEnumScript( iface );
01820 
01821     TRACE("%p %u\n", This, celt);
01822 
01823     if (celt >= This->total) return S_FALSE;
01824 
01825     This->pos += celt;
01826     return S_OK;
01827 }
01828 
01829 static const IEnumScriptVtbl IEnumScript_vtbl =
01830 {
01831     fnIEnumScript_QueryInterface,
01832     fnIEnumScript_AddRef,
01833     fnIEnumScript_Release,
01834     fnIEnumScript_Clone,
01835     fnIEnumScript_Next,
01836     fnIEnumScript_Reset,
01837     fnIEnumScript_Skip
01838 };
01839 
01840 static HRESULT EnumScript_create( MLang_impl* mlang, DWORD dwFlags,
01841                      LANGID LangId, IEnumScript** ppEnumScript )
01842 {
01843     EnumScript_impl *es;
01844     UINT i;
01845 
01846     TRACE("%p, %08x, %04x, %p: stub!\n", mlang, dwFlags, LangId, ppEnumScript);
01847 
01848     if (!dwFlags) /* enumerate all available scripts */
01849         dwFlags = SCRIPTCONTF_SCRIPT_USER | SCRIPTCONTF_SCRIPT_HIDE | SCRIPTCONTF_SCRIPT_SYSTEM;
01850 
01851     es = HeapAlloc( GetProcessHeap(), 0, sizeof (EnumScript_impl) );
01852     es->IEnumScript_iface.lpVtbl = &IEnumScript_vtbl;
01853     es->ref = 1;
01854     es->pos = 0;
01855     /* do not enumerate unicode flavours */
01856     es->total = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
01857     es->script_info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPTINFO) * es->total);
01858 
01859     for (i = 0; i < es->total; i++)
01860     {
01861         es->script_info[i].ScriptId = i;
01862         es->script_info[i].uiCodePage = mlang_data[i].family_codepage;
01863         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].description, -1,
01864             es->script_info[i].wszDescription, MAX_SCRIPT_NAME);
01865         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
01866             es->script_info[i].wszFixedWidthFont, MAX_MIMEFACE_NAME);
01867         MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
01868             es->script_info[i].wszProportionalFont, MAX_MIMEFACE_NAME);
01869     }
01870 
01871     TRACE("enumerated %d scripts with flags %08x\n", es->total, dwFlags);
01872 
01873     *ppEnumScript = &es->IEnumScript_iface;
01874 
01875     return S_OK;
01876 }
01877 
01878 /******************************************************************************/
01879 
01880 static inline MLang_impl *impl_from_IMLangFontLink( IMLangFontLink *iface )
01881 {
01882     return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink_iface );
01883 }
01884 
01885 static HRESULT WINAPI fnIMLangFontLink_QueryInterface(
01886         IMLangFontLink* iface,
01887         REFIID riid,
01888         void** ppvObject)
01889 {
01890     MLang_impl *This = impl_from_IMLangFontLink( iface );
01891     return MLang_QueryInterface( This, riid, ppvObject );
01892 }
01893 
01894 static ULONG WINAPI fnIMLangFontLink_AddRef(
01895         IMLangFontLink* iface)
01896 {
01897     MLang_impl *This = impl_from_IMLangFontLink( iface );
01898     return MLang_AddRef( This );
01899 }
01900 
01901 static ULONG WINAPI fnIMLangFontLink_Release(
01902         IMLangFontLink* iface)
01903 {
01904     MLang_impl *This = impl_from_IMLangFontLink( iface );
01905     return MLang_Release( This );
01906 }
01907 
01908 static HRESULT WINAPI fnIMLangFontLink_GetCharCodePages(
01909         IMLangFontLink* iface,
01910         WCHAR chSrc,
01911         DWORD* pdwCodePages)
01912 {
01913     int i;
01914     CHAR buf;
01915     BOOL used_dc;
01916     DWORD codePages;
01917 
01918     *pdwCodePages = 0;
01919 
01920     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
01921     {
01922         WideCharToMultiByte(mlang_data[i].family_codepage, WC_NO_BEST_FIT_CHARS,
01923             &chSrc, 1, &buf, 1, NULL, &used_dc);
01924 
01925         /* If default char is not used, current codepage include the given symbol */
01926         if (!used_dc)
01927         {
01928             IMLangFontLink_CodePageToCodePages(iface,
01929                 mlang_data[i].family_codepage, &codePages);
01930             *pdwCodePages |= codePages;
01931         }
01932     }
01933     return S_OK;
01934 }
01935 
01936 static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
01937         IMLangFontLink* iface,
01938         const WCHAR* pszSrc,
01939         LONG cchSrc,
01940         DWORD dwPriorityCodePages,
01941         DWORD* pdwCodePages,
01942         LONG* pcchCodePages)
01943 {
01944     LONG i;
01945     DWORD cps = 0;
01946 
01947     TRACE("(%p)->%s %d %x %p %p\n", iface, debugstr_wn(pszSrc, cchSrc), cchSrc, dwPriorityCodePages, pdwCodePages, pcchCodePages);
01948 
01949     if (pdwCodePages) *pdwCodePages = 0;
01950     if (pcchCodePages) *pcchCodePages = 0;
01951 
01952     if (!pszSrc || !cchSrc || cchSrc < 0)
01953         return E_INVALIDARG;
01954 
01955     for (i = 0; i < cchSrc; i++)
01956     {
01957         DWORD cp;
01958         HRESULT ret;
01959 
01960         ret = fnIMLangFontLink_GetCharCodePages(iface, pszSrc[i], &cp);
01961         if (ret != S_OK) return E_FAIL;
01962 
01963         if (!cps) cps = cp;
01964         else cps &= cp;
01965 
01966         /* FIXME: not tested */
01967         if (dwPriorityCodePages & cps) break;
01968     }
01969 
01970     if (pdwCodePages) *pdwCodePages = cps;
01971     if (pcchCodePages) *pcchCodePages = min( i + 1, cchSrc );
01972     return S_OK;
01973 }
01974 
01975 static HRESULT WINAPI fnIMLangFontLink_CodePageToCodePages(
01976         IMLangFontLink* iface,
01977         UINT uCodePage,
01978         DWORD* pdwCodePages)
01979 {
01980     MLang_impl *This = impl_from_IMLangFontLink( iface );
01981     CHARSETINFO cs;
01982     BOOL rc; 
01983 
01984     TRACE("(%p) Seeking %u\n",This, uCodePage);
01985 
01986     rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)uCodePage, &cs, TCI_SRCCODEPAGE);
01987 
01988     if (rc)
01989     {
01990         *pdwCodePages = cs.fs.fsCsb[0];
01991         TRACE("resulting CodePages 0x%x\n",*pdwCodePages);
01992         return S_OK;
01993     }
01994 
01995     TRACE("CodePage Not Found\n");
01996     *pdwCodePages = 0;
01997     return E_FAIL;
01998 }
01999 
02000 static HRESULT WINAPI fnIMLangFontLink_CodePagesToCodePage(
02001         IMLangFontLink* iface,
02002         DWORD dwCodePages,
02003         UINT uDefaultCodePage,
02004         UINT* puCodePage)
02005 {
02006     MLang_impl *This = impl_from_IMLangFontLink( iface );
02007     DWORD mask = 0x00000000;
02008     UINT i;
02009     CHARSETINFO cs;
02010     BOOL rc; 
02011 
02012     TRACE("(%p) scanning  0x%x  default page %u\n",This, dwCodePages,
02013             uDefaultCodePage);
02014 
02015     *puCodePage = 0x00000000;
02016 
02017     rc = TranslateCharsetInfo((DWORD*)(DWORD_PTR)uDefaultCodePage, &cs,
02018                               TCI_SRCCODEPAGE);
02019 
02020     if (rc && (dwCodePages & cs.fs.fsCsb[0]))
02021     {
02022         TRACE("Found Default Codepage\n");
02023         *puCodePage = uDefaultCodePage;
02024         return S_OK;
02025     }
02026 
02027     
02028     for (i = 0; i < 32; i++)
02029     {
02030 
02031         mask = 1 << i;
02032         if (dwCodePages & mask)
02033         {
02034             DWORD Csb[2];
02035             Csb[0] = mask;
02036             Csb[1] = 0x0;
02037             rc = TranslateCharsetInfo(Csb, &cs, TCI_SRCFONTSIG);
02038             if (!rc)
02039                 continue;
02040 
02041             TRACE("Falling back to least significant found CodePage %u\n",
02042                     cs.ciACP);
02043             *puCodePage = cs.ciACP;
02044             return S_OK;
02045         }
02046     }
02047 
02048     TRACE("no codepage found\n");
02049     return E_FAIL;
02050 }
02051 
02052 static HRESULT WINAPI fnIMLangFontLink_GetFontCodePages(
02053         IMLangFontLink* iface,
02054         HDC hDC,
02055         HFONT hFont,
02056         DWORD* pdwCodePages)
02057 {
02058     HFONT old_font;
02059     FONTSIGNATURE fontsig;
02060     MLang_impl *This = impl_from_IMLangFontLink( iface );
02061 
02062     TRACE("(%p)\n",This);
02063 
02064     old_font = SelectObject(hDC,hFont);
02065     GetTextCharsetInfo(hDC,&fontsig, 0);
02066     SelectObject(hDC,old_font);
02067 
02068     *pdwCodePages = fontsig.fsCsb[0];
02069     TRACE("CodePages is 0x%x\n",fontsig.fsCsb[0]);
02070 
02071     return S_OK;
02072 }
02073 
02074 static HRESULT WINAPI fnIMLangFontLink_MapFont(
02075         IMLangFontLink* iface,
02076         HDC hDC,
02077         DWORD dwCodePages,
02078         HFONT hSrcFont,
02079         HFONT* phDestFont)
02080 {
02081     FIXME("\n");
02082     return E_NOTIMPL;
02083 }
02084 
02085 static HRESULT WINAPI fnIMLangFontLink_ReleaseFont(
02086         IMLangFontLink* iface,
02087         HFONT hFont)
02088 {
02089     FIXME("\n");
02090     return E_NOTIMPL;
02091 }
02092 
02093 static HRESULT WINAPI fnIMLangFontLink_ResetFontMapping(
02094         IMLangFontLink* iface)
02095 {
02096     FIXME("\n");
02097     return E_NOTIMPL;
02098 }
02099 
02100 
02101 static const IMLangFontLinkVtbl IMLangFontLink_vtbl =
02102 {
02103     fnIMLangFontLink_QueryInterface,
02104     fnIMLangFontLink_AddRef,
02105     fnIMLangFontLink_Release,
02106     fnIMLangFontLink_GetCharCodePages,
02107     fnIMLangFontLink_GetStrCodePages,
02108     fnIMLangFontLink_CodePageToCodePages,
02109     fnIMLangFontLink_CodePagesToCodePage,
02110     fnIMLangFontLink_GetFontCodePages,
02111     fnIMLangFontLink_MapFont,
02112     fnIMLangFontLink_ReleaseFont,
02113     fnIMLangFontLink_ResetFontMapping,
02114 };
02115 
02116 /******************************************************************************/
02117 
02118 static inline MLang_impl *impl_from_IMultiLanguage( IMultiLanguage *iface )
02119 {
02120     return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage_iface );
02121 }
02122 
02123 static HRESULT WINAPI fnIMultiLanguage_QueryInterface(
02124     IMultiLanguage* iface,
02125     REFIID riid,
02126     void** ppvObject)
02127 {
02128     MLang_impl *This = impl_from_IMultiLanguage( iface );
02129     return MLang_QueryInterface( This, riid, ppvObject );
02130 }
02131 
02132 static ULONG WINAPI fnIMultiLanguage_AddRef( IMultiLanguage* iface )
02133 {
02134     MLang_impl *This = impl_from_IMultiLanguage( iface );
02135     return IMLangFontLink_AddRef( &This->IMLangFontLink_iface );
02136 }
02137 
02138 static ULONG WINAPI fnIMultiLanguage_Release( IMultiLanguage* iface )
02139 {
02140     MLang_impl *This = impl_from_IMultiLanguage( iface );
02141     return IMLangFontLink_Release( &This->IMLangFontLink_iface );
02142 }
02143 
02144 static HRESULT WINAPI fnIMultiLanguage_GetNumberOfCodePageInfo(
02145     IMultiLanguage* iface,
02146     UINT* pcCodePage)
02147 {
02148     MLang_impl *This = impl_from_IMultiLanguage( iface );
02149 
02150     TRACE("(%p, %p)\n", This, pcCodePage);
02151 
02152     if (!pcCodePage) return E_INVALIDARG;
02153 
02154     *pcCodePage = This->total_cp;
02155     return S_OK;
02156 }
02157 
02158 static HRESULT WINAPI fnIMultiLanguage_GetCodePageInfo(
02159     IMultiLanguage* iface,
02160     UINT uiCodePage,
02161     PMIMECPINFO pCodePageInfo)
02162 {
02163     UINT i, n;
02164     MLang_impl *This = impl_from_IMultiLanguage( iface );
02165 
02166     TRACE("%p, %u, %p\n", This, uiCodePage, pCodePageInfo);
02167 
02168     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
02169     {
02170         for (n = 0; n < mlang_data[i].number_of_cp; n++)
02171         {
02172             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
02173             {
02174                 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
02175                 return S_OK;
02176             }
02177         }
02178     }
02179 
02180     return S_FALSE;
02181 }
02182 
02183 static HRESULT WINAPI fnIMultiLanguage_GetFamilyCodePage(
02184     IMultiLanguage* iface,
02185     UINT uiCodePage,
02186     UINT* puiFamilyCodePage)
02187 {
02188     return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
02189 }
02190 
02191 static HRESULT WINAPI fnIMultiLanguage_EnumCodePages(
02192     IMultiLanguage* iface,
02193     DWORD grfFlags,
02194     IEnumCodePage** ppEnumCodePage)
02195 {
02196     MLang_impl *This = impl_from_IMultiLanguage( iface );
02197 
02198     TRACE("%p %08x %p\n", This, grfFlags, ppEnumCodePage);
02199 
02200     return EnumCodePage_create( This, grfFlags, 0, ppEnumCodePage );
02201 }
02202 
02203 static HRESULT WINAPI fnIMultiLanguage_GetCharsetInfo(
02204     IMultiLanguage* iface,
02205     BSTR Charset,
02206     PMIMECSETINFO pCharsetInfo)
02207 {
02208     MLang_impl *This = impl_from_IMultiLanguage( iface );
02209     return IMultiLanguage3_GetCharsetInfo( &This->IMultiLanguage3_iface, Charset, pCharsetInfo );
02210 }
02211 
02212 static HRESULT WINAPI fnIMultiLanguage_IsConvertible(
02213     IMultiLanguage* iface,
02214     DWORD dwSrcEncoding,
02215     DWORD dwDstEncoding)
02216 {
02217     return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
02218 }
02219 
02220 static HRESULT WINAPI fnIMultiLanguage_ConvertString(
02221     IMultiLanguage* iface,
02222     DWORD* pdwMode,
02223     DWORD dwSrcEncoding,
02224     DWORD dwDstEncoding,
02225     BYTE* pSrcStr,
02226     UINT* pcSrcSize,
02227     BYTE* pDstStr,
02228     UINT* pcDstSize)
02229 {
02230     return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
02231         (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
02232 }
02233 
02234 static HRESULT WINAPI fnIMultiLanguage_ConvertStringToUnicode(
02235     IMultiLanguage* iface,
02236     DWORD* pdwMode,
02237     DWORD dwEncoding,
02238     CHAR* pSrcStr,
02239     UINT* pcSrcSize,
02240     WCHAR* pDstStr,
02241     UINT* pcDstSize)
02242 {
02243     return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
02244         (LPCSTR)pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
02245 }
02246 
02247 static HRESULT WINAPI fnIMultiLanguage_ConvertStringFromUnicode(
02248     IMultiLanguage* iface,
02249     DWORD* pdwMode,
02250     DWORD dwEncoding,
02251     WCHAR* pSrcStr,
02252     UINT* pcSrcSize,
02253     CHAR* pDstStr,
02254     UINT* pcDstSize)
02255 {
02256     return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
02257         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
02258 }
02259 
02260 static HRESULT WINAPI fnIMultiLanguage_ConvertStringReset(
02261     IMultiLanguage* iface)
02262 {
02263     FIXME("\n");
02264     return E_NOTIMPL;
02265 }
02266 
02267 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766FromLcid(
02268     IMultiLanguage* iface,
02269     LCID lcid,
02270     BSTR* pbstrRfc1766)
02271 {
02272     WCHAR buf[MAX_RFC1766_NAME];
02273 
02274     TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
02275     if (!pbstrRfc1766)
02276         return E_INVALIDARG;
02277 
02278     if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
02279     {
02280         *pbstrRfc1766 = SysAllocString( buf );
02281         return S_OK;
02282     }
02283     return E_FAIL;
02284 }
02285 
02286 static HRESULT WINAPI fnIMultiLanguage_GetLcidFromRfc1766(
02287     IMultiLanguage* iface,
02288     LCID* pLocale,
02289     BSTR bstrRfc1766)
02290 {
02291     HRESULT hr;
02292     IEnumRfc1766 *rfc1766;
02293 
02294     TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
02295 
02296     if (!pLocale || !bstrRfc1766)
02297         return E_INVALIDARG;
02298 
02299     hr = IMultiLanguage_EnumRfc1766(iface, &rfc1766);
02300     if (FAILED(hr))
02301         return hr;
02302 
02303     hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
02304 
02305     IEnumRfc1766_Release(rfc1766);
02306     return hr;
02307 }
02308 
02309 /******************************************************************************/
02310 
02311 typedef struct tagEnumRfc1766_impl
02312 {
02313     IEnumRfc1766 IEnumRfc1766_iface;
02314     LONG ref;
02315     RFC1766INFO *info;
02316     DWORD total, pos;
02317 } EnumRfc1766_impl;
02318 
02319 static inline EnumRfc1766_impl *impl_from_IEnumRfc1766( IEnumRfc1766 *iface )
02320 {
02321     return CONTAINING_RECORD( iface, EnumRfc1766_impl, IEnumRfc1766_iface );
02322 }
02323 
02324 static HRESULT WINAPI fnIEnumRfc1766_QueryInterface(
02325         IEnumRfc1766 *iface,
02326         REFIID riid,
02327         void** ppvObject)
02328 {
02329     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
02330 
02331     TRACE("%p -> %s\n", This, debugstr_guid(riid) );
02332 
02333     if (IsEqualGUID(riid, &IID_IUnknown)
02334         || IsEqualGUID(riid, &IID_IEnumRfc1766))
02335     {
02336         IEnumRfc1766_AddRef(iface);
02337         TRACE("Returning IID_IEnumRfc1766 %p ref = %d\n", This, This->ref);
02338         *ppvObject = &This->IEnumRfc1766_iface;
02339         return S_OK;
02340     }
02341 
02342     WARN("(%p) -> (%s,%p), not found\n",This,debugstr_guid(riid),ppvObject);
02343     return E_NOINTERFACE;
02344 }
02345 
02346 static ULONG WINAPI fnIEnumRfc1766_AddRef(
02347         IEnumRfc1766 *iface)
02348 {
02349     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
02350     return InterlockedIncrement(&This->ref);
02351 }
02352 
02353 static ULONG WINAPI fnIEnumRfc1766_Release(
02354         IEnumRfc1766 *iface)
02355 {
02356     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
02357     ULONG ref = InterlockedDecrement(&This->ref);
02358 
02359     TRACE("%p ref = %d\n", This, ref);
02360     if (ref == 0)
02361     {
02362         TRACE("Destroying %p\n", This);
02363         HeapFree(GetProcessHeap(), 0, This->info);
02364         HeapFree(GetProcessHeap(), 0, This);
02365     }
02366     return ref;
02367 }
02368 
02369 static HRESULT WINAPI fnIEnumRfc1766_Clone(
02370         IEnumRfc1766 *iface,
02371         IEnumRfc1766 **ppEnum)
02372 {
02373     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
02374 
02375     FIXME("%p %p\n", This, ppEnum);
02376     return E_NOTIMPL;
02377 }
02378 
02379 static  HRESULT WINAPI fnIEnumRfc1766_Next(
02380         IEnumRfc1766 *iface,
02381         ULONG celt,
02382         PRFC1766INFO rgelt,
02383         ULONG *pceltFetched)
02384 {
02385     ULONG i;
02386     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
02387 
02388     TRACE("%p %u %p %p\n", This, celt, rgelt, pceltFetched);
02389 
02390     if (!pceltFetched) return S_FALSE;
02391     *pceltFetched = 0;
02392 
02393     if (!rgelt) return S_FALSE;
02394 
02395     if (This->pos + celt > This->total)
02396         celt = This->total - This->pos;
02397 
02398     if (!celt) return S_FALSE;
02399 
02400     memcpy(rgelt, This->info + This->pos, celt * sizeof(RFC1766INFO));
02401     *pceltFetched = celt;
02402     This->pos += celt;
02403 
02404     for (i = 0; i < celt; i++)
02405     {
02406         TRACE("#%u: %08x %s %s\n",
02407               i, rgelt[i].lcid,
02408               wine_dbgstr_w(rgelt[i].wszRfc1766),
02409               wine_dbgstr_w(rgelt[i].wszLocaleName));
02410     }
02411     return S_OK;
02412 }
02413 
02414 static HRESULT WINAPI fnIEnumRfc1766_Reset(
02415         IEnumRfc1766 *iface)
02416 {
02417     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
02418 
02419     TRACE("%p\n", This);
02420 
02421     This->pos = 0;
02422     return S_OK;
02423 }
02424 
02425 static  HRESULT WINAPI fnIEnumRfc1766_Skip(
02426         IEnumRfc1766 *iface,
02427         ULONG celt)
02428 {
02429     EnumRfc1766_impl *This = impl_from_IEnumRfc1766( iface );
02430 
02431     TRACE("%p %u\n", This, celt);
02432 
02433     if (celt >= This->total) return S_FALSE;
02434 
02435     This->pos += celt;
02436     return S_OK;
02437 }
02438 
02439 static const IEnumRfc1766Vtbl IEnumRfc1766_vtbl =
02440 {
02441     fnIEnumRfc1766_QueryInterface,
02442     fnIEnumRfc1766_AddRef,
02443     fnIEnumRfc1766_Release,
02444     fnIEnumRfc1766_Clone,
02445     fnIEnumRfc1766_Next,
02446     fnIEnumRfc1766_Reset,
02447     fnIEnumRfc1766_Skip
02448 };
02449 
02450 struct enum_locales_data
02451 {
02452     RFC1766INFO *info;
02453     DWORD total, allocated;
02454 };
02455 
02456 static BOOL CALLBACK enum_locales_proc(LPWSTR locale)
02457 {
02458     WCHAR *end;
02459     struct enum_locales_data *data = TlsGetValue(MLANG_tls_index);
02460     RFC1766INFO *info;
02461 
02462     TRACE("%s\n", debugstr_w(locale));
02463 
02464     if (data->total >= data->allocated)
02465     {
02466         data->allocated += 32;
02467         data->info = HeapReAlloc(GetProcessHeap(), 0, data->info, data->allocated * sizeof(RFC1766INFO));
02468         if (!data->info) return FALSE;
02469     }
02470 
02471     info = &data->info[data->total];
02472 
02473     info->lcid = strtolW(locale, &end, 16);
02474     if (*end) /* invalid number */
02475         return FALSE;
02476 
02477     info->wszRfc1766[0] = 0;
02478     lcid_to_rfc1766W( info->lcid, info->wszRfc1766, MAX_RFC1766_NAME );
02479 
02480     info->wszLocaleName[0] = 0;
02481     GetLocaleInfoW(info->lcid, LOCALE_SLANGUAGE, info->wszLocaleName, MAX_LOCALE_NAME);
02482     TRACE("ISO639: %s SLANGUAGE: %s\n", wine_dbgstr_w(info->wszRfc1766), wine_dbgstr_w(info->wszLocaleName));
02483     
02484     data->total++;
02485 
02486     return TRUE;
02487 }
02488 
02489 static HRESULT EnumRfc1766_create(LANGID LangId, IEnumRfc1766 **ppEnum)
02490 {
02491     EnumRfc1766_impl *rfc;
02492     struct enum_locales_data data;
02493 
02494     TRACE("%04x, %p\n", LangId, ppEnum);
02495 
02496     rfc = HeapAlloc( GetProcessHeap(), 0, sizeof(EnumRfc1766_impl) );
02497     rfc->IEnumRfc1766_iface.lpVtbl = &IEnumRfc1766_vtbl;
02498     rfc->ref = 1;
02499     rfc->pos = 0;
02500     rfc->total = 0;
02501 
02502     data.total = 0;
02503     data.allocated = 160;
02504     data.info = HeapAlloc(GetProcessHeap(), 0, data.allocated * sizeof(RFC1766INFO));
02505     if (!data.info)
02506     {
02507         HeapFree(GetProcessHeap(), 0, rfc);
02508         return E_OUTOFMEMORY;
02509     }
02510 
02511     TlsSetValue(MLANG_tls_index, &data);
02512     EnumSystemLocalesW(enum_locales_proc, 0/*LOCALE_SUPPORTED*/);
02513     TlsSetValue(MLANG_tls_index, NULL);
02514 
02515     TRACE("enumerated %d rfc1766 structures\n", data.total);
02516 
02517     if (!data.total)
02518     {
02519         HeapFree(GetProcessHeap(), 0, data.info);
02520         HeapFree(GetProcessHeap(), 0, rfc);
02521         return E_FAIL;
02522     }
02523 
02524     rfc->info = data.info;
02525     rfc->total = data.total;
02526 
02527     *ppEnum = &rfc->IEnumRfc1766_iface;
02528     return S_OK;
02529 }
02530 
02531 static HRESULT WINAPI fnIMultiLanguage_EnumRfc1766(
02532     IMultiLanguage *iface,
02533     IEnumRfc1766 **ppEnumRfc1766)
02534 {
02535     MLang_impl *This = impl_from_IMultiLanguage( iface );
02536 
02537     TRACE("%p %p\n", This, ppEnumRfc1766);
02538 
02539     return EnumRfc1766_create(0, ppEnumRfc1766);
02540 }
02541 
02542 /******************************************************************************/
02543 
02544 static HRESULT WINAPI fnIMultiLanguage_GetRfc1766Info(
02545     IMultiLanguage* iface,
02546     LCID Locale,
02547     PRFC1766INFO pRfc1766Info)
02548 {
02549     LCTYPE type = LOCALE_SLANGUAGE;
02550 
02551     TRACE("(%p, 0x%04x, %p)\n", iface, Locale, pRfc1766Info);
02552 
02553     if (!pRfc1766Info)
02554         return E_INVALIDARG;
02555 
02556     if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
02557         (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
02558         (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
02559 
02560         if (!SUBLANGID(Locale))
02561             type = LOCALE_SENGLANGUAGE; /* suppress country */
02562     }
02563     else
02564     {
02565         if (!SUBLANGID(Locale)) {
02566             TRACE("SUBLANGID missing in 0x%04x\n", Locale);
02567             return E_FAIL;
02568         }
02569     }
02570 
02571     pRfc1766Info->lcid = Locale;
02572     pRfc1766Info->wszRfc1766[0] = 0;
02573     pRfc1766Info->wszLocaleName[0] = 0;
02574 
02575     if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
02576         (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
02577             return S_OK;
02578 
02579     /* Locale not supported */
02580     return E_INVALIDARG;
02581 }
02582 
02583 static HRESULT WINAPI fnIMultiLanguage_CreateConvertCharset(
02584     IMultiLanguage* iface,
02585     UINT uiSrcCodePage,
02586     UINT uiDstCodePage,
02587     DWORD dwProperty,
02588     IMLangConvertCharset** ppMLangConvertCharset)
02589 {
02590     FIXME("\n");
02591     return E_NOTIMPL;
02592 }
02593 
02594 static const IMultiLanguageVtbl IMultiLanguage_vtbl =
02595 {
02596     fnIMultiLanguage_QueryInterface,
02597     fnIMultiLanguage_AddRef,
02598     fnIMultiLanguage_Release,
02599     fnIMultiLanguage_GetNumberOfCodePageInfo,
02600     fnIMultiLanguage_GetCodePageInfo,
02601     fnIMultiLanguage_GetFamilyCodePage,
02602     fnIMultiLanguage_EnumCodePages,
02603     fnIMultiLanguage_GetCharsetInfo,
02604     fnIMultiLanguage_IsConvertible,
02605     fnIMultiLanguage_ConvertString,
02606     fnIMultiLanguage_ConvertStringToUnicode,
02607     fnIMultiLanguage_ConvertStringFromUnicode,
02608     fnIMultiLanguage_ConvertStringReset,
02609     fnIMultiLanguage_GetRfc1766FromLcid,
02610     fnIMultiLanguage_GetLcidFromRfc1766,
02611     fnIMultiLanguage_EnumRfc1766,
02612     fnIMultiLanguage_GetRfc1766Info,
02613     fnIMultiLanguage_CreateConvertCharset,
02614 };
02615 
02616 
02617 /******************************************************************************/
02618 
02619 static inline MLang_impl *impl_from_IMultiLanguage3( IMultiLanguage3 *iface )
02620 {
02621     return CONTAINING_RECORD( iface, MLang_impl, IMultiLanguage3_iface );
02622 }
02623 
02624 static HRESULT WINAPI fnIMultiLanguage2_QueryInterface(
02625     IMultiLanguage3* iface,
02626     REFIID riid,
02627     void** ppvObject)
02628 {
02629     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02630     return MLang_QueryInterface( This, riid, ppvObject );
02631 }
02632 
02633 static ULONG WINAPI fnIMultiLanguage2_AddRef( IMultiLanguage3* iface )
02634 {
02635     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02636     return MLang_AddRef( This );
02637 }
02638 
02639 static ULONG WINAPI fnIMultiLanguage2_Release( IMultiLanguage3* iface )
02640 {
02641     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02642     return MLang_Release( This );
02643 }
02644 
02645 static HRESULT WINAPI fnIMultiLanguage2_GetNumberOfCodePageInfo(
02646     IMultiLanguage3* iface,
02647     UINT* pcCodePage)
02648 {
02649     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02650 
02651     TRACE("%p, %p\n", This, pcCodePage);
02652 
02653     if (!pcCodePage) return E_INVALIDARG;
02654 
02655     *pcCodePage = This->total_cp;
02656     return S_OK;
02657 }
02658 
02659 static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info)
02660 {
02661     CHARSETINFO csi;
02662 
02663     if (TranslateCharsetInfo((DWORD*)(DWORD_PTR)ml_data->family_codepage, &csi,
02664                              TCI_SRCCODEPAGE))
02665         mime_cp_info->bGDICharset = csi.ciCharset;
02666     else
02667         mime_cp_info->bGDICharset = DEFAULT_CHARSET;
02668 
02669     mime_cp_info->dwFlags = ml_data->mime_cp_info[index].flags;
02670     mime_cp_info->uiCodePage = ml_data->mime_cp_info[index].cp;
02671     mime_cp_info->uiFamilyCodePage = ml_data->family_codepage;
02672     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].description, -1,
02673                         mime_cp_info->wszDescription, sizeof(mime_cp_info->wszDescription)/sizeof(WCHAR));
02674     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].web_charset, -1,
02675                         mime_cp_info->wszWebCharset, sizeof(mime_cp_info->wszWebCharset)/sizeof(WCHAR));
02676     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].header_charset, -1,
02677                         mime_cp_info->wszHeaderCharset, sizeof(mime_cp_info->wszHeaderCharset)/sizeof(WCHAR));
02678     MultiByteToWideChar(CP_ACP, 0, ml_data->mime_cp_info[index].body_charset, -1,
02679                         mime_cp_info->wszBodyCharset, sizeof(mime_cp_info->wszBodyCharset)/sizeof(WCHAR));
02680 
02681     MultiByteToWideChar(CP_ACP, 0, ml_data->fixed_font, -1,
02682         mime_cp_info->wszFixedWidthFont, sizeof(mime_cp_info->wszFixedWidthFont)/sizeof(WCHAR));
02683     MultiByteToWideChar(CP_ACP, 0, ml_data->proportional_font, -1,
02684         mime_cp_info->wszProportionalFont, sizeof(mime_cp_info->wszProportionalFont)/sizeof(WCHAR));
02685 
02686     TRACE("%08x %u %u %s %s %s %s %s %s %d\n",
02687           mime_cp_info->dwFlags, mime_cp_info->uiCodePage,
02688           mime_cp_info->uiFamilyCodePage,
02689           wine_dbgstr_w(mime_cp_info->wszDescription),
02690           wine_dbgstr_w(mime_cp_info->wszWebCharset),
02691           wine_dbgstr_w(mime_cp_info->wszHeaderCharset),
02692           wine_dbgstr_w(mime_cp_info->wszBodyCharset),
02693           wine_dbgstr_w(mime_cp_info->wszFixedWidthFont),
02694           wine_dbgstr_w(mime_cp_info->wszProportionalFont),
02695           mime_cp_info->bGDICharset);
02696 }
02697 
02698 static HRESULT WINAPI fnIMultiLanguage2_GetCodePageInfo(
02699     IMultiLanguage3* iface,
02700     UINT uiCodePage,
02701     LANGID LangId,
02702     PMIMECPINFO pCodePageInfo)
02703 {
02704     UINT i, n;
02705     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02706 
02707     TRACE("%p, %u, %04x, %p\n", This, uiCodePage, LangId, pCodePageInfo);
02708 
02709     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
02710     {
02711         for (n = 0; n < mlang_data[i].number_of_cp; n++)
02712         {
02713             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
02714             {
02715                 fill_cp_info(&mlang_data[i], n, pCodePageInfo);
02716                 return S_OK;
02717             }
02718         }
02719     }
02720 
02721     return S_FALSE;
02722 }
02723 
02724 static HRESULT WINAPI fnIMultiLanguage2_GetFamilyCodePage(
02725     IMultiLanguage3* iface,
02726     UINT uiCodePage,
02727     UINT* puiFamilyCodePage)
02728 {
02729     return GetFamilyCodePage(uiCodePage, puiFamilyCodePage);
02730 }
02731 
02732 static HRESULT WINAPI fnIMultiLanguage2_EnumCodePages(
02733     IMultiLanguage3* iface,
02734     DWORD grfFlags,
02735     LANGID LangId,
02736     IEnumCodePage** ppEnumCodePage)
02737 {
02738     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02739 
02740     TRACE("%p %08x %04x %p\n", This, grfFlags, LangId, ppEnumCodePage);
02741 
02742     return EnumCodePage_create( This, grfFlags, LangId, ppEnumCodePage );
02743 }
02744 
02745 static HRESULT WINAPI fnIMultiLanguage2_GetCharsetInfo(
02746     IMultiLanguage3* iface,
02747     BSTR Charset,
02748     PMIMECSETINFO pCharsetInfo)
02749 {
02750     UINT i, n;
02751     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02752 
02753     TRACE("%p %s %p\n", This, debugstr_w(Charset), pCharsetInfo);
02754 
02755     if (!pCharsetInfo) return E_FAIL;
02756 
02757     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
02758     {
02759         for (n = 0; n < mlang_data[i].number_of_cp; n++)
02760         {
02761             WCHAR csetW[MAX_MIMECSET_NAME];
02762 
02763             MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].web_charset, -1, csetW, MAX_MIMECSET_NAME);
02764             if (!lstrcmpiW(Charset, csetW))
02765             {
02766                 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
02767                 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
02768                 strcpyW(pCharsetInfo->wszCharset, csetW);
02769                 return S_OK;
02770             }
02771         }
02772     }
02773 
02774     /* FIXME:
02775      * Since we do not support charsets like iso-2022-jp and do not have
02776      * them in our database as a primary (web_charset) encoding this loop
02777      * does an attempt to 'approximate' charset name by header_charset.
02778      */
02779     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
02780     {
02781         for (n = 0; n < mlang_data[i].number_of_cp; n++)
02782         {
02783             WCHAR csetW[MAX_MIMECSET_NAME];
02784 
02785             MultiByteToWideChar(CP_ACP, 0, mlang_data[i].mime_cp_info[n].header_charset, -1, csetW, MAX_MIMECSET_NAME);
02786             if (!lstrcmpiW(Charset, csetW))
02787             {
02788                 pCharsetInfo->uiCodePage = mlang_data[i].family_codepage;
02789                 pCharsetInfo->uiInternetEncoding = mlang_data[i].mime_cp_info[n].cp;
02790                 strcpyW(pCharsetInfo->wszCharset, csetW);
02791                 return S_OK;
02792             }
02793         }
02794     }
02795 
02796     return E_FAIL;
02797 }
02798 
02799 static HRESULT WINAPI fnIMultiLanguage2_IsConvertible(
02800     IMultiLanguage3* iface,
02801     DWORD dwSrcEncoding,
02802     DWORD dwDstEncoding)
02803 {
02804     return IsConvertINetStringAvailable(dwSrcEncoding, dwDstEncoding);
02805 }
02806 
02807 static HRESULT WINAPI fnIMultiLanguage2_ConvertString(
02808     IMultiLanguage3* iface,
02809     DWORD* pdwMode,
02810     DWORD dwSrcEncoding,
02811     DWORD dwDstEncoding,
02812     BYTE* pSrcStr,
02813     UINT* pcSrcSize,
02814     BYTE* pDstStr,
02815     UINT* pcDstSize)
02816 {
02817     return ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding,
02818         (LPCSTR)pSrcStr, (LPINT)pcSrcSize, (LPSTR)pDstStr, (LPINT)pcDstSize);
02819 }
02820 
02821 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringToUnicode(
02822     IMultiLanguage3* iface,
02823     DWORD* pdwMode,
02824     DWORD dwEncoding,
02825     CHAR* pSrcStr,
02826     UINT* pcSrcSize,
02827     WCHAR* pDstStr,
02828     UINT* pcDstSize)
02829 {
02830     return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
02831         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
02832 }
02833 
02834 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringFromUnicode(
02835     IMultiLanguage3* iface,
02836     DWORD* pdwMode,
02837     DWORD dwEncoding,
02838     WCHAR* pSrcStr,
02839     UINT* pcSrcSize,
02840     CHAR* pDstStr,
02841     UINT* pcDstSize)
02842 {
02843     return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
02844         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
02845 }
02846 
02847 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringReset(
02848     IMultiLanguage3* iface)
02849 {
02850     FIXME("\n");
02851     return E_NOTIMPL;
02852 }
02853 
02854 static HRESULT WINAPI fnIMultiLanguage2_GetRfc1766FromLcid(
02855     IMultiLanguage3* iface,
02856     LCID lcid,
02857     BSTR* pbstrRfc1766)
02858 {
02859     WCHAR buf[MAX_RFC1766_NAME];
02860 
02861     TRACE("%p %04x %p\n", iface, lcid, pbstrRfc1766);
02862     if (!pbstrRfc1766)
02863         return E_INVALIDARG;
02864 
02865     if (!lcid_to_rfc1766W( lcid, buf, MAX_RFC1766_NAME ))
02866     {
02867         *pbstrRfc1766 = SysAllocString( buf );
02868         return S_OK;
02869     }
02870     return E_FAIL;
02871 }
02872 
02873 static HRESULT WINAPI fnIMultiLanguage2_GetLcidFromRfc1766(
02874     IMultiLanguage3* iface,
02875     LCID* pLocale,
02876     BSTR bstrRfc1766)
02877 {
02878     HRESULT hr;
02879     IEnumRfc1766 *rfc1766;
02880 
02881     TRACE("%p %p %s\n", iface, pLocale, debugstr_w(bstrRfc1766));
02882 
02883     if (!pLocale || !bstrRfc1766)
02884         return E_INVALIDARG;
02885 
02886     hr = IMultiLanguage2_EnumRfc1766(iface, 0, &rfc1766);
02887     if (FAILED(hr))
02888         return hr;
02889 
02890     hr = lcid_from_rfc1766(rfc1766, pLocale, bstrRfc1766);
02891 
02892     IEnumRfc1766_Release(rfc1766);
02893     return hr;
02894 }
02895 
02896 static HRESULT WINAPI fnIMultiLanguage2_EnumRfc1766(
02897     IMultiLanguage3* iface,
02898     LANGID LangId,
02899     IEnumRfc1766** ppEnumRfc1766)
02900 {
02901     MLang_impl *This = impl_from_IMultiLanguage3( iface );
02902 
02903     TRACE("%p %p\n", This, ppEnumRfc1766);
02904 
02905     return EnumRfc1766_create(LangId, ppEnumRfc1766);
02906 }
02907 
02908 static HRESULT WINAPI fnIMultiLanguage2_GetRfc1766Info(
02909     IMultiLanguage3* iface,
02910     LCID Locale,
02911     LANGID LangId,
02912     PRFC1766INFO pRfc1766Info)
02913 {
02914     static LANGID last_lang = -1;
02915     LCTYPE type = LOCALE_SLANGUAGE;
02916 
02917     TRACE("(%p, 0x%04x, 0x%04x, %p)\n", iface, Locale, LangId, pRfc1766Info);
02918 
02919     if (!pRfc1766Info)
02920         return E_INVALIDARG;
02921 
02922     if ((PRIMARYLANGID(Locale) == LANG_ENGLISH) ||
02923         (PRIMARYLANGID(Locale) == LANG_CHINESE) ||
02924         (PRIMARYLANGID(Locale) == LANG_ARABIC)) {
02925 
02926         if (!SUBLANGID(Locale))
02927             type = LOCALE_SENGLANGUAGE; /* suppress country */
02928     }
02929     else
02930     {
02931         if (!SUBLANGID(Locale)) {
02932             TRACE("SUBLANGID missing in 0x%04x\n", Locale);
02933             return E_FAIL;
02934         }
02935     }
02936 
02937     pRfc1766Info->lcid = Locale;
02938     pRfc1766Info->wszRfc1766[0] = 0;
02939     pRfc1766Info->wszLocaleName[0] = 0;
02940 
02941     if ((PRIMARYLANGID(LangId) != LANG_ENGLISH) &&
02942         (last_lang != LangId)) {
02943         FIXME("Only English names supported (requested: 0x%04x)\n", LangId);
02944         last_lang = LangId;
02945     }
02946 
02947     if ((!lcid_to_rfc1766W(Locale, pRfc1766Info->wszRfc1766, MAX_RFC1766_NAME)) &&
02948         (GetLocaleInfoW(Locale, type, pRfc1766Info->wszLocaleName, MAX_LOCALE_NAME) > 0))
02949             return S_OK;
02950 
02951     /* Locale not supported */
02952     return E_INVALIDARG;
02953 }
02954 
02955 static HRESULT WINAPI fnIMultiLanguage2_CreateConvertCharset(
02956     IMultiLanguage3* iface,
02957     UINT uiSrcCodePage,
02958     UINT uiDstCodePage,
02959     DWORD dwProperty,
02960     IMLangConvertCharset** ppMLangConvertCharset)
02961 {
02962     FIXME("\n");
02963     return E_NOTIMPL;
02964 }
02965 
02966 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringInIStream(
02967     IMultiLanguage3* iface,
02968     DWORD* pdwMode,
02969     DWORD dwFlag,
02970     WCHAR* lpFallBack,
02971     DWORD dwSrcEncoding,
02972     DWORD dwDstEncoding,
02973     IStream* pstmIn,
02974     IStream* pstmOut)
02975 {
02976     char *src, *dst = NULL;
02977     INT srclen, dstlen;
02978     STATSTG stat;
02979     HRESULT hr;
02980 
02981     TRACE("%p %0x8 %s %u %u %p %p\n",
02982           pdwMode, dwFlag, debugstr_w(lpFallBack), dwSrcEncoding, dwDstEncoding, pstmIn, pstmOut);
02983 
02984     FIXME("dwFlag and lpFallBack not handled\n");
02985 
02986     hr = IStream_Stat(pstmIn, &stat, STATFLAG_NONAME);
02987     if (FAILED(hr)) return hr;
02988 
02989     if (stat.cbSize.QuadPart > MAXLONG) return E_INVALIDARG;
02990     if (!(src = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart))) return E_OUTOFMEMORY;
02991 
02992     hr = IStream_Read(pstmIn, src, stat.cbSize.QuadPart, (ULONG *)&srclen);
02993     if (FAILED(hr)) goto exit;
02994 
02995     hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, NULL, &dstlen);
02996     if (FAILED(hr)) goto exit;
02997 
02998     if (!(dst = HeapAlloc(GetProcessHeap(), 0, dstlen)))
02999     {
03000         hr = E_OUTOFMEMORY;
03001         goto exit;
03002     }
03003     hr = ConvertINetString(pdwMode, dwSrcEncoding, dwDstEncoding, src, &srclen, dst, &dstlen);
03004     if (FAILED(hr)) goto exit;
03005 
03006     hr = IStream_Write(pstmOut, dst, dstlen, NULL);
03007 
03008 exit:
03009     HeapFree(GetProcessHeap(), 0, src);
03010     HeapFree(GetProcessHeap(), 0, dst);
03011     return hr;
03012 }
03013 
03014 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringToUnicodeEx(
03015     IMultiLanguage3* iface,
03016     DWORD* pdwMode,
03017     DWORD dwEncoding,
03018     CHAR* pSrcStr,
03019     UINT* pcSrcSize,
03020     WCHAR* pDstStr,
03021     UINT* pcDstSize,
03022     DWORD dwFlag,
03023     WCHAR* lpFallBack)
03024 {
03025     if (dwFlag || lpFallBack)
03026         FIXME("Ignoring dwFlag (0x%x/%d) and lpFallBack (%p)\n",
03027                 dwFlag, dwFlag, lpFallBack);
03028 
03029     return ConvertINetMultiByteToUnicode(pdwMode, dwEncoding,
03030         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
03031 }
03032 
03033 /*****************************************************************************
03034  * MultiLanguage2::ConvertStringToUnicodeEx
03035  *
03036  * Translates the multibyte string from the specified code page to Unicode.
03037  *
03038  * PARAMS
03039  *   see ConvertStringToUnicode
03040  *   dwFlag 
03041  *   lpFallBack if dwFlag contains MLCONVCHARF_USEDEFCHAR, lpFallBack string used
03042  *              instead unconvertible characters.
03043  *
03044  * RETURNS
03045  *   S_OK     Success.
03046  *   S_FALSE  The conversion is not supported.
03047  *   E_FAIL   Some error has occurred.
03048  *
03049  * TODO: handle dwFlag and lpFallBack
03050 */
03051 static HRESULT WINAPI fnIMultiLanguage2_ConvertStringFromUnicodeEx(
03052     IMultiLanguage3* This,
03053     DWORD* pdwMode,
03054     DWORD dwEncoding,
03055     WCHAR* pSrcStr,
03056     UINT* pcSrcSize,
03057     CHAR* pDstStr,
03058     UINT* pcDstSize,
03059     DWORD dwFlag,
03060     WCHAR* lpFallBack)
03061 {
03062     FIXME("\n");
03063     return ConvertINetUnicodeToMultiByte(pdwMode, dwEncoding,
03064         pSrcStr, (LPINT)pcSrcSize, pDstStr, (LPINT)pcDstSize);
03065 }
03066 
03067 static HRESULT WINAPI fnIMultiLanguage2_DetectCodepageInIStream(
03068     IMultiLanguage3* iface,
03069     DWORD dwFlag,
03070     DWORD dwPrefWinCodePage,
03071     IStream* pstmIn,
03072     DetectEncodingInfo* lpEncoding,
03073     INT* pnScores)
03074 {
03075     FIXME("\n");
03076     return E_NOTIMPL;
03077 }
03078 
03079 static HRESULT WINAPI fnIMultiLanguage2_DetectInputCodepage(
03080     IMultiLanguage3* iface,
03081     DWORD dwFlag,
03082     DWORD dwPrefWinCodePage,
03083     CHAR* pSrcStr,
03084     INT* pcSrcSize,
03085     DetectEncodingInfo* lpEncoding,
03086     INT* pnScores)
03087 {
03088     FIXME("\n");
03089     return E_NOTIMPL;
03090 }
03091 
03092 static HRESULT WINAPI fnIMultiLanguage2_ValidateCodePage(
03093     IMultiLanguage3* iface,
03094     UINT uiCodePage,
03095     HWND hwnd)
03096 {
03097     return IMultiLanguage2_ValidateCodePageEx(iface,uiCodePage,hwnd,0);
03098 }
03099 
03100 static HRESULT WINAPI fnIMultiLanguage2_GetCodePageDescription(
03101     IMultiLanguage3* iface,
03102     UINT uiCodePage,
03103     LCID lcid,
03104     LPWSTR lpWideCharStr,
03105     int cchWideChar)
03106 {
03107     /* Find first instance */
03108     unsigned int i,n;
03109 
03110     TRACE ("%u, %04x, %p, %d\n", uiCodePage, lcid, lpWideCharStr, cchWideChar);
03111     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
03112     {
03113         for (n = 0; n < mlang_data[i].number_of_cp; n++)
03114         {
03115             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
03116             {
03117                 MultiByteToWideChar(CP_ACP, 0,
03118                                     mlang_data[i].mime_cp_info[n].description,
03119                                     -1, lpWideCharStr, cchWideChar);
03120                 return S_OK;
03121             }
03122         }
03123     }
03124 
03125     return S_FALSE;
03126 }
03127 
03128 static HRESULT WINAPI fnIMultiLanguage2_IsCodePageInstallable(
03129     IMultiLanguage3* iface,
03130     UINT uiCodePage)
03131 {
03132     TRACE("%u\n", uiCodePage);
03133 
03134     /* FIXME: the installable set is usually larger than the set of valid codepages */
03135     return IMultiLanguage2_ValidateCodePageEx(iface, uiCodePage, NULL, CPIOD_PEEK);
03136 }
03137 
03138 static HRESULT WINAPI fnIMultiLanguage2_SetMimeDBSource(
03139     IMultiLanguage3* iface,
03140     MIMECONTF dwSource)
03141 {
03142     FIXME("0x%08x\n", dwSource);
03143     return S_OK;
03144 }
03145 
03146 static HRESULT WINAPI fnIMultiLanguage2_GetNumberOfScripts(
03147     IMultiLanguage3* iface,
03148     UINT* pnScripts)
03149 {
03150     MLang_impl *This = impl_from_IMultiLanguage3( iface );
03151 
03152     TRACE("%p %p\n", This, pnScripts);
03153 
03154     if (!pnScripts) return S_FALSE;
03155 
03156     *pnScripts = This->total_scripts;
03157     return S_OK;
03158 }
03159 
03160 static HRESULT WINAPI fnIMultiLanguage2_EnumScripts(
03161     IMultiLanguage3* iface,
03162     DWORD dwFlags,
03163     LANGID LangId,
03164     IEnumScript** ppEnumScript)
03165 {
03166     MLang_impl *This = impl_from_IMultiLanguage3( iface );
03167 
03168     TRACE("%p %08x %04x %p\n", This, dwFlags, LangId, ppEnumScript);
03169 
03170     return EnumScript_create( This, dwFlags, LangId, ppEnumScript );
03171 }
03172 
03173 static HRESULT WINAPI fnIMultiLanguage2_ValidateCodePageEx(
03174     IMultiLanguage3* iface,
03175     UINT uiCodePage,
03176     HWND hwnd,
03177     DWORD dwfIODControl)
03178 {
03179     int i;
03180     MLang_impl *This = impl_from_IMultiLanguage3( iface );
03181 
03182     TRACE("%p %u %p %08x\n", This, uiCodePage, hwnd, dwfIODControl);
03183 
03184     /* quick check for kernel32 supported code pages */
03185     if (IsValidCodePage(uiCodePage))
03186         return S_OK;
03187 
03188     /* check for mlang supported code pages */
03189     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
03190     {
03191         int n;
03192         for (n = 0; n < mlang_data[i].number_of_cp; n++)
03193         {
03194             if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
03195                 return S_OK;
03196         }
03197     }
03198 
03199     if (dwfIODControl != CPIOD_PEEK)
03200         FIXME("Request to install codepage language pack not handled\n");
03201 
03202     return S_FALSE;
03203 }
03204 
03205 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePage(
03206     IMultiLanguage3 *iface,
03207     DWORD dwFlags,
03208     LPCWSTR lpWideCharStr,
03209     UINT cchWideChar,
03210     UINT *puiPreferredCodePages,
03211     UINT nPreferredCodePages,
03212     UINT *puiDetectedCodePages,
03213     UINT *pnDetectedCodePages,
03214     WCHAR *lpSpecialChar)
03215 {
03216     MLang_impl *This = impl_from_IMultiLanguage3( iface );
03217 
03218     FIXME("(%p)->(%08x %s %u %p %u %p %p %p)\n", This, dwFlags, debugstr_w(lpWideCharStr),
03219           cchWideChar, puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
03220           pnDetectedCodePages, lpSpecialChar);
03221     return E_NOTIMPL;
03222 }
03223 
03224 static HRESULT WINAPI fnIMultiLanguage3_DetectOutboundCodePageInIStream(
03225     IMultiLanguage3 *iface,
03226     DWORD dwFlags,
03227     IStream *pStrIn,
03228     UINT *puiPreferredCodePages,
03229     UINT nPreferredCodePages,
03230     UINT *puiDetectedCodePages,
03231     UINT *pnDetectedCodePages,
03232     WCHAR *lpSpecialChar)
03233 {
03234     MLang_impl *This = impl_from_IMultiLanguage3( iface );
03235 
03236     FIXME("(%p)->(%08x %p %p %u %p %p %p)\n", This, dwFlags, pStrIn,
03237           puiPreferredCodePages, nPreferredCodePages, puiDetectedCodePages,
03238           pnDetectedCodePages, lpSpecialChar);
03239     return E_NOTIMPL;
03240 }
03241 
03242 static const IMultiLanguage3Vtbl IMultiLanguage3_vtbl =
03243 {
03244     fnIMultiLanguage2_QueryInterface,
03245     fnIMultiLanguage2_AddRef,
03246     fnIMultiLanguage2_Release,
03247     fnIMultiLanguage2_GetNumberOfCodePageInfo,
03248     fnIMultiLanguage2_GetCodePageInfo,
03249     fnIMultiLanguage2_GetFamilyCodePage,
03250     fnIMultiLanguage2_EnumCodePages,
03251     fnIMultiLanguage2_GetCharsetInfo,
03252     fnIMultiLanguage2_IsConvertible,
03253     fnIMultiLanguage2_ConvertString,
03254     fnIMultiLanguage2_ConvertStringToUnicode,
03255     fnIMultiLanguage2_ConvertStringFromUnicode,
03256     fnIMultiLanguage2_ConvertStringReset,
03257     fnIMultiLanguage2_GetRfc1766FromLcid,
03258     fnIMultiLanguage2_GetLcidFromRfc1766,
03259     fnIMultiLanguage2_EnumRfc1766,
03260     fnIMultiLanguage2_GetRfc1766Info,
03261     fnIMultiLanguage2_CreateConvertCharset,
03262     fnIMultiLanguage2_ConvertStringInIStream,
03263     fnIMultiLanguage2_ConvertStringToUnicodeEx,
03264     fnIMultiLanguage2_ConvertStringFromUnicodeEx,
03265     fnIMultiLanguage2_DetectCodepageInIStream,
03266     fnIMultiLanguage2_DetectInputCodepage,
03267     fnIMultiLanguage2_ValidateCodePage,
03268     fnIMultiLanguage2_GetCodePageDescription,
03269     fnIMultiLanguage2_IsCodePageInstallable,
03270     fnIMultiLanguage2_SetMimeDBSource,
03271     fnIMultiLanguage2_GetNumberOfScripts,
03272     fnIMultiLanguage2_EnumScripts,
03273     fnIMultiLanguage2_ValidateCodePageEx,
03274     fnIMultiLanguage3_DetectOutboundCodePage,
03275     fnIMultiLanguage3_DetectOutboundCodePageInIStream
03276 };
03277 
03278 /******************************************************************************/
03279 
03280 static inline MLang_impl *impl_from_IMLangFontLink2( IMLangFontLink2 *iface )
03281 {
03282     return CONTAINING_RECORD( iface, MLang_impl, IMLangFontLink2_iface );
03283 }
03284 
03285 static HRESULT WINAPI fnIMLangFontLink2_QueryInterface(
03286     IMLangFontLink2 * iface,
03287     REFIID riid,
03288     void** ppvObject)
03289 {
03290     MLang_impl *This = impl_from_IMLangFontLink2( iface );
03291     return MLang_QueryInterface( This, riid, ppvObject );
03292 }
03293 
03294 static ULONG WINAPI fnIMLangFontLink2_AddRef( IMLangFontLink2* iface )
03295 {
03296     MLang_impl *This = impl_from_IMLangFontLink2( iface );
03297     return MLang_AddRef( This );
03298 }
03299 
03300 static ULONG WINAPI fnIMLangFontLink2_Release( IMLangFontLink2* iface )
03301 {
03302     MLang_impl *This = impl_from_IMLangFontLink2( iface );
03303     return MLang_Release( This );
03304 }
03305 
03306 static HRESULT WINAPI fnIMLangFontLink2_GetCharCodePages( IMLangFontLink2* This,
03307         WCHAR chSrc, DWORD *pdwCodePages)
03308 {
03309     FIXME("(%p)->%s %p\n",This, debugstr_wn(&chSrc,1),pdwCodePages);
03310     return E_NOTIMPL;
03311 }
03312 
03313 static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* This,
03314         const WCHAR *pszSrc, LONG cchSrc, DWORD dwPriorityCodePages,
03315         DWORD *pdwCodePages, LONG *pcchCodePages)
03316 {
03317     return fnIMLangFontLink_GetStrCodePages((IMLangFontLink *)This,
03318             pszSrc, cchSrc, dwPriorityCodePages, pdwCodePages, pcchCodePages);
03319 }
03320 
03321 static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* This,
03322         UINT uCodePage,
03323         DWORD *pdwCodePages)
03324 {
03325     FIXME("(%p)->%i %p\n",This, uCodePage, pdwCodePages);
03326     return E_NOTIMPL;
03327 }
03328 
03329 static HRESULT WINAPI fnIMLangFontLink2_CodePagesToCodePage(IMLangFontLink2* This,
03330         DWORD dwCodePages, UINT uDefaultCodePage, UINT *puCodePage)
03331 {
03332     FIXME("(%p)->%i %i %p\n",This, dwCodePages, uDefaultCodePage, puCodePage);
03333     return E_NOTIMPL;
03334 }
03335 
03336 static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2* This,
03337         HDC hDC, HFONT hFont, DWORD *pdwCodePages)
03338 {
03339     FIXME("(%p)->%p %p %p\n",This, hDC, hFont, pdwCodePages);
03340     return E_NOTIMPL;
03341 }
03342 
03343 static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
03344         HFONT hFont)
03345 {
03346     FIXME("(%p)->%p\n",This, hFont);
03347     return E_NOTIMPL;
03348 }
03349 
03350 static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
03351 {
03352     FIXME("(%p)->\n",This);
03353     return E_NOTIMPL;
03354 }
03355 
03356 static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
03357         HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
03358 {
03359     FIXME("(%p)->%p %i %s %p\n",This, hDC, dwCodePages, debugstr_wn(&chSrc,1), pFont);
03360     return E_NOTIMPL;
03361 }
03362 
03363 static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
03364         HDC hDC, UINT *puiRanges, UNICODERANGE *pUranges)
03365 {
03366     DWORD size;
03367     GLYPHSET *gs;
03368 
03369     TRACE("(%p)->%p %p %p\n", This, hDC, puiRanges, pUranges);
03370 
03371     if (!puiRanges) return E_INVALIDARG;
03372     if (!(size = GetFontUnicodeRanges(hDC, NULL))) return E_FAIL;
03373     if (!(gs = HeapAlloc(GetProcessHeap(), 0, size))) return E_OUTOFMEMORY;
03374 
03375     GetFontUnicodeRanges(hDC, gs);
03376     *puiRanges = gs->cRanges;
03377     if (pUranges)
03378     {
03379         UINT i;
03380         for (i = 0; i < gs->cRanges; i++)
03381         {
03382             if (i >= *puiRanges) break;
03383             pUranges[i].wcFrom = gs->ranges[i].wcLow;
03384             pUranges[i].wcTo   = gs->ranges[i].wcLow + gs->ranges[i].cGlyphs;
03385         }
03386         *puiRanges = i;
03387     }
03388     HeapFree(GetProcessHeap(), 0, gs);
03389     return S_OK;
03390 }
03391 
03392 static HRESULT WINAPI fnIMLangFontLink2_GetScriptFontInfo(IMLangFontLink2* This,
03393         SCRIPT_ID sid, DWORD dwFlags, UINT *puiFonts,
03394         SCRIPTFONTINFO *pScriptFont)
03395 {
03396     UINT i, j;
03397 
03398     TRACE("(%p)->%u %x %p %p\n", This, sid, dwFlags, puiFonts, pScriptFont);
03399 
03400     if (!dwFlags) dwFlags = SCRIPTCONTF_PROPORTIONAL_FONT;
03401 
03402     for (i = 0, j = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
03403     {
03404         if (sid == mlang_data[i].sid)
03405         {
03406             if (pScriptFont)
03407             {
03408                 if (j >= *puiFonts) break;
03409 
03410                 pScriptFont[j].scripts = 1 << mlang_data[i].sid;
03411                 if (dwFlags == SCRIPTCONTF_FIXED_FONT)
03412                 {
03413                     MultiByteToWideChar(CP_ACP, 0, mlang_data[i].fixed_font, -1,
03414                         pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
03415                 }
03416                 else if (dwFlags == SCRIPTCONTF_PROPORTIONAL_FONT)
03417                 {
03418                     MultiByteToWideChar(CP_ACP, 0, mlang_data[i].proportional_font, -1,
03419                         pScriptFont[j].wszFont, MAX_MIMEFACE_NAME);
03420                 }
03421             }
03422             j++;
03423         }
03424     }
03425     *puiFonts = j;
03426     return S_OK;
03427 }
03428 
03429 static HRESULT WINAPI fnIMLangFontLink2_CodePageToScriptID(IMLangFontLink2* This,
03430         UINT uiCodePage, SCRIPT_ID *pSid)
03431 {
03432     UINT i;
03433 
03434     TRACE("(%p)->%i %p\n", This, uiCodePage, pSid);
03435 
03436     if (uiCodePage == CP_UNICODE) return E_FAIL;
03437 
03438     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
03439     {
03440         if (uiCodePage == mlang_data[i].family_codepage)
03441         {
03442             if (pSid) *pSid = mlang_data[i].sid;
03443             return S_OK;
03444         }
03445     }
03446     return E_FAIL;
03447 }
03448 
03449 static const IMLangFontLink2Vtbl IMLangFontLink2_vtbl =
03450 {
03451     fnIMLangFontLink2_QueryInterface,
03452     fnIMLangFontLink2_AddRef,
03453     fnIMLangFontLink2_Release,
03454     fnIMLangFontLink2_GetCharCodePages,
03455     fnIMLangFontLink2_GetStrCodePages,
03456     fnIMLangFontLink2_CodePageToCodePages,
03457     fnIMLangFontLink2_CodePagesToCodePage,
03458     fnIMLangFontLink2_GetFontCodePages,
03459     fnIMLangFontLink2_ReleaseFont,
03460     fnIMLangFontLink2_ResetFontMapping,
03461     fnIMLangFontLink2_MapFont,
03462     fnIMLangFontLink2_GetFontUnicodeRanges,
03463     fnIMLangFontLink2_GetScriptFontInfo,
03464     fnIMLangFontLink2_CodePageToScriptID
03465 };
03466 
03467 /******************************************************************************/
03468 
03469 static inline MLang_impl *impl_from_IMLangLineBreakConsole( IMLangLineBreakConsole *iface )
03470 {
03471     return CONTAINING_RECORD( iface, MLang_impl, IMLangLineBreakConsole_iface );
03472 }
03473 
03474 static HRESULT WINAPI fnIMLangLineBreakConsole_QueryInterface(
03475     IMLangLineBreakConsole* iface,
03476     REFIID riid,
03477     void** ppvObject)
03478 {
03479     MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
03480     return MLang_QueryInterface( This, riid, ppvObject );
03481 }
03482 
03483 static ULONG WINAPI fnIMLangLineBreakConsole_AddRef(
03484     IMLangLineBreakConsole* iface )
03485 {
03486     MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
03487     return MLang_AddRef( This );
03488 }
03489 
03490 static ULONG WINAPI fnIMLangLineBreakConsole_Release(
03491     IMLangLineBreakConsole* iface )
03492 {
03493     MLang_impl *This = impl_from_IMLangLineBreakConsole( iface );
03494     return MLang_Release( This );
03495 }
03496 
03497 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineML(
03498     IMLangLineBreakConsole* iface,
03499     IMLangString* pSrcMLStr,
03500     LONG lSrcPos,
03501     LONG lSrcLen,
03502     LONG cMinColumns,
03503     LONG cMaxColumns,
03504     LONG* plLineLen,
03505     LONG* plSkipLen)
03506 {
03507     FIXME("(%p)->%p %i %i %i %i %p %p\n", iface, pSrcMLStr, lSrcPos, lSrcLen, cMinColumns, cMaxColumns, plLineLen, plSkipLen);
03508     return E_NOTIMPL;
03509 }
03510 
03511 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineW(
03512     IMLangLineBreakConsole* iface,
03513     LCID locale,
03514     const WCHAR* pszSrc,
03515     LONG cchSrc,
03516     LONG cMaxColumns,
03517     LONG* pcchLine,
03518     LONG* pcchSkip )
03519 {
03520     FIXME("(%p)->%i %s %i %i %p %p\n", iface, locale, debugstr_wn(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
03521 
03522     *pcchLine = cchSrc;
03523     *pcchSkip = 0;
03524     return S_OK;
03525 }
03526 
03527 static HRESULT WINAPI fnIMLangLineBreakConsole_BreakLineA(
03528     IMLangLineBreakConsole* iface,
03529     LCID locale,
03530     UINT uCodePage,
03531     const CHAR* pszSrc,
03532     LONG cchSrc,
03533     LONG cMaxColumns,
03534     LONG* pcchLine,
03535     LONG* pcchSkip)
03536 {
03537     FIXME("(%p)->%i %i %s %i %i %p %p\n", iface, locale, uCodePage, debugstr_an(pszSrc,cchSrc), cchSrc, cMaxColumns, pcchLine, pcchSkip);
03538 
03539     *pcchLine = cchSrc;
03540     *pcchSkip = 0;
03541     return S_OK;
03542 }
03543 
03544 static const IMLangLineBreakConsoleVtbl IMLangLineBreakConsole_vtbl =
03545 {
03546     fnIMLangLineBreakConsole_QueryInterface,
03547     fnIMLangLineBreakConsole_AddRef,
03548     fnIMLangLineBreakConsole_Release,
03549     fnIMLangLineBreakConsole_BreakLineML,
03550     fnIMLangLineBreakConsole_BreakLineW,
03551     fnIMLangLineBreakConsole_BreakLineA
03552 };
03553 
03554 static HRESULT MultiLanguage_create(IUnknown *pUnkOuter, LPVOID *ppObj)
03555 {
03556     MLang_impl *mlang;
03557     UINT i;
03558 
03559     TRACE("Creating MultiLanguage object\n");
03560 
03561     if( pUnkOuter )
03562         return CLASS_E_NOAGGREGATION;
03563 
03564     mlang = HeapAlloc( GetProcessHeap(), 0, sizeof (MLang_impl) );
03565     mlang->IMLangFontLink_iface.lpVtbl = &IMLangFontLink_vtbl;
03566     mlang->IMultiLanguage_iface.lpVtbl = &IMultiLanguage_vtbl;
03567     mlang->IMultiLanguage3_iface.lpVtbl = &IMultiLanguage3_vtbl;
03568     mlang->IMLangFontLink2_iface.lpVtbl = &IMLangFontLink2_vtbl;
03569     mlang->IMLangLineBreakConsole_iface.lpVtbl = &IMLangLineBreakConsole_vtbl;
03570 
03571     mlang->total_cp = 0;
03572     for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
03573         mlang->total_cp += mlang_data[i].number_of_cp;
03574 
03575     /* do not enumerate unicode flavours */
03576     mlang->total_scripts = sizeof(mlang_data)/sizeof(mlang_data[0]) - 1;
03577 
03578     mlang->ref = 1;
03579     *ppObj = mlang;
03580     TRACE("returning %p\n", mlang);
03581 
03582     LockModule();
03583 
03584     return S_OK;
03585 }
03586 
03587 /******************************************************************************/
03588 
03589 HRESULT WINAPI DllCanUnloadNow(void)
03590 {
03591     return dll_count == 0 ? S_OK : S_FALSE;
03592 }
03593 
03594 
03595 /***********************************************************************
03596  *      DllRegisterServer (MLANG.@)
03597  */
03598 HRESULT WINAPI DllRegisterServer(void)
03599 {
03600     return __wine_register_resources( instance );
03601 }
03602 
03603 /***********************************************************************
03604  *      DllUnregisterServer (MLANG.@)
03605  */
03606 HRESULT WINAPI DllUnregisterServer(void)
03607 {
03608     return __wine_unregister_resources( instance );
03609 }
03610 
03611 HRESULT WINAPI GetGlobalFontLinkObject(void **unknown)
03612 {
03613     if (!unknown) return E_INVALIDARG;
03614 
03615     FIXME("%p: stub\n", unknown);
03616 
03617     return S_FALSE;
03618 }

Generated on Sun May 27 2012 04:24:41 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.