📄 mlang.c
字号:
UINT number_of_cp;
const MIME_CP_INFO *mime_cp_info;
const char *fixed_font;
const char *proportional_font;
} mlang_data[] =
{
{ "Arabic",1256,sizeof(arabic_cp)/sizeof(arabic_cp[0]),arabic_cp,
"Courier","Arial" }, /* FIXME */
{ "Baltic",1257,sizeof(baltic_cp)/sizeof(baltic_cp[0]),baltic_cp,
"Courier","Arial" }, /* FIXME */
{ "Chinese Simplified",936,sizeof(chinese_simplified_cp)/sizeof(chinese_simplified_cp[0]),chinese_simplified_cp,
"Courier","Arial" }, /* FIXME */
{ "Chinese Traditional",950,sizeof(chinese_traditional_cp)/sizeof(chinese_traditional_cp[0]),chinese_traditional_cp,
"Courier","Arial" }, /* FIXME */
{ "Central European",1250,sizeof(central_european_cp)/sizeof(central_european_cp[0]),central_european_cp,
"Courier","Arial" }, /* FIXME */
{ "Cyrillic",1251,sizeof(cyrillic_cp)/sizeof(cyrillic_cp[0]),cyrillic_cp,
"Courier","Arial" }, /* FIXME */
{ "Greek",1253,sizeof(greek_cp)/sizeof(greek_cp[0]),greek_cp,
"Courier","Arial" }, /* FIXME */
{ "Hebrew",1255,sizeof(hebrew_cp)/sizeof(hebrew_cp[0]),hebrew_cp,
"Courier","Arial" }, /* FIXME */
{ "Japanese",932,sizeof(japanese_cp)/sizeof(japanese_cp[0]),japanese_cp,
"Courier","Arial" }, /* FIXME */
{ "Korean",949,sizeof(korean_cp)/sizeof(korean_cp[0]),korean_cp,
"Courier","Arial" }, /* FIXME */
{ "Thai",874,sizeof(thai_cp)/sizeof(thai_cp[0]),thai_cp,
"Courier","Arial" }, /* FIXME */
{ "Turkish",1254,sizeof(turkish_cp)/sizeof(turkish_cp[0]),turkish_cp,
"Courier","Arial" }, /* FIXME */
{ "Vietnamese",1258,sizeof(vietnamese_cp)/sizeof(vietnamese_cp[0]),vietnamese_cp,
"Courier","Arial" }, /* FIXME */
{ "Western European",1252,sizeof(western_cp)/sizeof(western_cp[0]),western_cp,
"Courier","Arial" }, /* FIXME */
{ "Unicode",CP_UNICODE,sizeof(unicode_cp)/sizeof(unicode_cp[0]),unicode_cp,
"Courier","Arial" } /* FIXME */
};
static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
static LONG dll_count;
/*
* Dll lifetime tracking declaration
*/
static void LockModule(void)
{
InterlockedIncrement(&dll_count);
}
static void UnlockModule(void)
{
InterlockedDecrement(&dll_count);
}
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
MLANG_tls_index = TlsAlloc();
DisableThreadLibraryCalls(hInstDLL);
break;
case DLL_PROCESS_DETACH:
TlsFree(MLANG_tls_index);
break;
}
return TRUE;
}
HRESULT WINAPI ConvertINetMultiByteToUnicode(
LPDWORD pdwMode,
DWORD dwEncoding,
LPCSTR pSrcStr,
LPINT pcSrcSize,
LPWSTR pDstStr,
LPINT pcDstSize)
{
INT src_len = -1;
TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
if (!pcDstSize)
return E_FAIL;
if (!pcSrcSize)
pcSrcSize = &src_len;
if (!*pcSrcSize)
{
*pcDstSize = 0;
return S_OK;
}
switch (dwEncoding)
{
case CP_UNICODE:
if (*pcSrcSize == -1)
*pcSrcSize = lstrlenW((LPCWSTR)pSrcStr);
*pcDstSize = min(*pcSrcSize, *pcDstSize);
*pcSrcSize *= sizeof(WCHAR);
if (pDstStr)
memmove(pDstStr, pSrcStr, *pcDstSize * sizeof(WCHAR));
break;
default:
if (*pcSrcSize == -1)
*pcSrcSize = lstrlenA(pSrcStr);
if (pDstStr)
*pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize);
else
*pcDstSize = MultiByteToWideChar(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0);
break;
}
if (!*pcDstSize)
return E_FAIL;
return S_OK;
}
HRESULT WINAPI ConvertINetUnicodeToMultiByte(
LPDWORD pdwMode,
DWORD dwEncoding,
LPCWSTR pSrcStr,
LPINT pcSrcSize,
LPSTR pDstStr,
LPINT pcDstSize)
{
INT src_len = -1;
TRACE("%p %d %s %p %p %p\n", pdwMode, dwEncoding,
debugstr_w(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
if (!pcDstSize)
return E_FAIL;
if (!pcSrcSize)
pcSrcSize = &src_len;
if (!*pcSrcSize)
{
*pcDstSize = 0;
return S_OK;
}
switch (dwEncoding)
{
case CP_UNICODE:
if (*pcSrcSize == -1)
*pcSrcSize = lstrlenW(pSrcStr);
*pcDstSize = min(*pcSrcSize * sizeof(WCHAR), *pcDstSize);
if (pDstStr)
memmove(pDstStr, pSrcStr, *pcDstSize);
break;
default:
if (*pcSrcSize == -1)
*pcSrcSize = lstrlenW(pSrcStr);
if (pDstStr)
*pcDstSize = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize, pDstStr, *pcDstSize, NULL, NULL);
else
*pcDstSize = WideCharToMultiByte(dwEncoding, 0, pSrcStr, *pcSrcSize, NULL, 0, NULL, NULL);
break;
}
if (!*pcDstSize)
return E_FAIL;
return S_OK;
}
HRESULT WINAPI ConvertINetString(
LPDWORD pdwMode,
DWORD dwSrcEncoding,
DWORD dwDstEncoding,
LPCSTR pSrcStr,
LPINT pcSrcSize,
LPSTR pDstStr,
LPINT pcDstSize
)
{
TRACE("%p %d %d %s %p %p %p\n", pdwMode, dwSrcEncoding, dwDstEncoding,
debugstr_a(pSrcStr), pcSrcSize, pDstStr, pcDstSize);
if (dwSrcEncoding == CP_UNICODE)
{
INT cSrcSizeW;
if (pcSrcSize && *pcSrcSize != -1)
{
cSrcSizeW = *pcSrcSize / sizeof(WCHAR);
pcSrcSize = &cSrcSizeW;
}
return ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, (LPCWSTR)pSrcStr, pcSrcSize, pDstStr, pcDstSize);
}
else if (dwDstEncoding == CP_UNICODE)
{
HRESULT hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, (LPWSTR)pDstStr, pcDstSize);
*pcDstSize *= sizeof(WCHAR);
return hr;
}
else
{
INT cDstSizeW;
LPWSTR pDstStrW;
HRESULT hr;
TRACE("convert %s from %d to %d\n", debugstr_a(pSrcStr), dwSrcEncoding, dwDstEncoding);
hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, NULL, &cDstSizeW);
if (hr != S_OK)
return hr;
pDstStrW = HeapAlloc(GetProcessHeap(), 0, cDstSizeW * sizeof(WCHAR));
hr = ConvertINetMultiByteToUnicode(pdwMode, dwSrcEncoding, pSrcStr, pcSrcSize, pDstStrW, &cDstSizeW);
if (hr != S_OK)
return hr;
hr = ConvertINetUnicodeToMultiByte(pdwMode, dwDstEncoding, pDstStrW, &cDstSizeW, pDstStr, pcDstSize);
HeapFree(GetProcessHeap(), 0, pDstStrW);
return hr;
}
}
static HRESULT GetFamilyCodePage(
UINT uiCodePage,
UINT* puiFamilyCodePage)
{
UINT i, n;
TRACE("%u %p\n", uiCodePage, puiFamilyCodePage);
if (!puiFamilyCodePage) return S_FALSE;
for (i = 0; i < sizeof(mlang_data)/sizeof(mlang_data[0]); i++)
{
for (n = 0; n < mlang_data[i].number_of_cp; n++)
{
if (mlang_data[i].mime_cp_info[n].cp == uiCodePage)
{
*puiFamilyCodePage = mlang_data[i].family_codepage;
return S_OK;
}
}
}
return S_FALSE;
}
HRESULT WINAPI IsConvertINetStringAvailable(
DWORD dwSrcEncoding,
DWORD dwDstEncoding)
{
UINT src_family, dst_family;
TRACE("%d %d\n", dwSrcEncoding, dwDstEncoding);
if (GetFamilyCodePage(dwSrcEncoding, &src_family) != S_OK ||
GetFamilyCodePage(dwDstEncoding, &dst_family) != S_OK)
return S_FALSE;
if (src_family == dst_family) return S_OK;
/* we can convert any codepage to/from unicode */
if (src_family == CP_UNICODE || dst_family == CP_UNICODE) return S_OK;
return S_FALSE;
}
static inline INT lcid_to_rfc1766A( LCID lcid, LPSTR rfc1766, INT len )
{
INT n = GetLocaleInfoA( lcid, LOCALE_SISO639LANGNAME, rfc1766, len );
if (n)
{
rfc1766[n - 1] = '-';
n += GetLocaleInfoA( lcid, LOCALE_SISO3166CTRYNAME, rfc1766 + n, len - n ) + 1;
LCMapStringA( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, rfc1766, n, rfc1766, len );
return n;
}
return 0;
}
static inline INT lcid_to_rfc1766W( LCID lcid, LPWSTR rfc1766, INT len )
{
INT n = GetLocaleInfoW( lcid, LOCALE_SISO639LANGNAME, rfc1766, len );
if (n)
{
rfc1766[n - 1] = '-';
n += GetLocaleInfoW( lcid, LOCALE_SISO3166CTRYNAME, rfc1766 + n, len - n ) + 1;
LCMapStringW( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, rfc1766, n, rfc1766, len );
return n;
}
return 0;
}
HRESULT WINAPI LcidToRfc1766A(
LCID lcid,
LPSTR pszRfc1766,
INT nChar)
{
TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
if (lcid_to_rfc1766A( lcid, pszRfc1766, nChar ))
return S_OK;
return S_FALSE;
}
HRESULT WINAPI LcidToRfc1766W(
LCID lcid,
LPWSTR pszRfc1766,
INT nChar)
{
TRACE("%04x %p %u\n", lcid, pszRfc1766, nChar);
if (lcid_to_rfc1766W( lcid, pszRfc1766, nChar ))
return S_OK;
return S_FALSE;
}
static HRESULT lcid_from_rfc1766(IEnumRfc1766 *iface, LCID *lcid, LPCWSTR rfc1766)
{
RFC1766INFO info;
ULONG num;
while (IEnumRfc1766_Next(iface, 1, &info, &num) == S_OK)
{
if (!strcmpW(info.wszRfc1766, rfc1766))
{
*lcid = info.lcid;
return S_OK;
}
if (strlenW(rfc1766) == 2 && !memcmp(info.wszRfc1766, rfc1766, 2 * sizeof(WCHAR)))
{
*lcid = PRIMARYLANGID(info.lcid);
return S_OK;
}
}
return E_FAIL;
}
/******************************************************************************
* MLANG ClassFactory
*/
typedef struct {
IClassFactory ITF_IClassFactory;
LONG ref;
HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
} IClassFactoryImpl;
struct object_creation_info
{
const CLSID *clsid;
LPCSTR szClassName;
HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
};
static const struct object_creation_info object_creation[] =
{
{ &CLSID_CMultiLanguage, "CLSID_CMultiLanguage", MultiLanguage_create },
};
static HRESULT WINAPI
MLANGCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
TRACE("%s\n", debugstr_guid(riid) );
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IClassFactory))
{
IClassFactory_AddRef(iface);
*ppobj = This;
return S_OK;
}
WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI MLANGCF_AddRef(LPCLASSFACTORY iface)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI MLANGCF_Release(LPCLASSFACTORY iface)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
ULONG ref = InterlockedDecrement(&This->ref);
if (ref == 0)
{
TRACE("Destroying %p\n", This);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
static HRESULT WINAPI MLANGCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
REFIID riid, LPVOID *ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
HRESULT hres;
LPUNKNOWN punk;
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -