You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
635 lines
18 KiB
635 lines
18 KiB
#include "private.h"
|
|
#include "mui.h"
|
|
#include "immxutil.h"
|
|
#include "ciccs.h"
|
|
|
|
struct Tag_MuiInfo
|
|
{
|
|
HINSTANCE hinstLocRes;
|
|
HINSTANCE hinstOrg;
|
|
TCHAR szLocResDll[MAX_PATH];
|
|
TCHAR szCodePage[10];
|
|
DWORD dwCodePage;
|
|
BOOL fLoaded;
|
|
} g_muiInfo;
|
|
|
|
typedef struct
|
|
{
|
|
LANGID langid;
|
|
BOOL fFoundLang;
|
|
} ENUMLANGDATA;
|
|
|
|
typedef BOOL (WINAPI *PFNGETFILEVERSIONINFO)(LPTSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
|
|
typedef DWORD (WINAPI *PFNGETFILEVERSIONINFOSIZE)(LPTSTR lptstrFilename, LPDWORD lpdwHandle);
|
|
typedef BOOL (WINAPI *PFNVERQUERYVALUE)(const LPVOID pBlock, LPTSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen);
|
|
|
|
static struct
|
|
{
|
|
PFNGETFILEVERSIONINFO pfnGetFileVersionInfo;
|
|
PFNGETFILEVERSIONINFOSIZE pfnGetFileVersionInfoSize;
|
|
PFNVERQUERYVALUE pfnVerQueryValue;
|
|
} g_VersionFuncTbl = { 0 };
|
|
|
|
static HINSTANCE g_hVersion = NULL;
|
|
|
|
CCicCriticalSectionStatic g_csMuiLib;
|
|
|
|
static BOOL g_bEnableMui = FALSE;
|
|
|
|
const TCHAR c_szMuiDir[] = TEXT("\\mui\\fallback\\");
|
|
const TCHAR c_szMuiExt[] = TEXT(".mui");
|
|
const TCHAR c_szVerTranslate[] = TEXT("\\VarFileInfo\\Translation");
|
|
|
|
#define VERSIONSIZE 11
|
|
#define VERSION_MINOR_INDEX 9
|
|
|
|
typedef UINT (WINAPI *PFNGETSYSTEMWINDOWSDIRECTORY) (LPSTR lpBuffer, UINT uSize);
|
|
static PFNGETSYSTEMWINDOWSDIRECTORY pfnGetSystemWindowsDirectory = NULL;
|
|
|
|
|
|
BOOL GetFileVersionString(LPSTR pszFileName, LPTSTR pszVerStr, UINT uVerStrLen);
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiResAssure
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
__inline void MuiResAssure()
|
|
{
|
|
if(g_bEnableMui && g_muiInfo.hinstLocRes == NULL && !g_muiInfo.fLoaded)
|
|
{
|
|
g_muiInfo.hinstLocRes = MuiLoadLibrary(g_muiInfo.szLocResDll,
|
|
g_muiInfo.hinstOrg);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiLoadResource
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MuiLoadResource(HINSTANCE hinstOrg, LPTSTR pszLocResDll)
|
|
{
|
|
LANGID langRes = 0;
|
|
|
|
InitOSVer();
|
|
|
|
if (!g_csMuiLib.Init())
|
|
return;
|
|
|
|
if (!IsOnNT51())
|
|
g_bEnableMui = TRUE;
|
|
|
|
if (g_muiInfo.hinstLocRes == NULL)
|
|
{
|
|
if (g_bEnableMui)
|
|
{
|
|
g_muiInfo.hinstOrg = hinstOrg;
|
|
|
|
StringCchCopy(g_muiInfo.szLocResDll,
|
|
ARRAYSIZE(g_muiInfo.szLocResDll),
|
|
pszLocResDll);
|
|
}
|
|
else
|
|
{
|
|
g_muiInfo.hinstLocRes = hinstOrg;
|
|
}
|
|
}
|
|
|
|
langRes = GetPlatformResourceLangID();
|
|
|
|
GetLocaleInfo(MAKELCID(langRes, SORT_DEFAULT),
|
|
LOCALE_IDEFAULTANSICODEPAGE,
|
|
g_muiInfo.szCodePage,
|
|
ARRAYSIZE(g_muiInfo.szCodePage));
|
|
|
|
if (!AsciiToNumDec(g_muiInfo.szCodePage, &g_muiInfo.dwCodePage) ||
|
|
IsValidCodePage(g_muiInfo.dwCodePage) == 0)
|
|
{
|
|
g_muiInfo.dwCodePage = GetACP();
|
|
}
|
|
|
|
g_muiInfo.fLoaded = FALSE;
|
|
}
|
|
|
|
void MuiLoadResourceW(HINSTANCE hinstOrg, LPWSTR pszLocResDll)
|
|
{
|
|
TCHAR szResName[MAX_PATH];
|
|
|
|
WideCharToMultiByte(1252, NULL, pszLocResDll, -1, szResName, MAX_PATH, NULL, NULL);
|
|
|
|
return MuiLoadResource(hinstOrg, szResName);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiFlushDlls
|
|
//
|
|
// Call this routine to free all loaded dlls.
|
|
// Caller can keep using mui apis, the dlls will be reloaded on demand.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MuiFlushDlls(HINSTANCE hinstOrg)
|
|
{
|
|
if (g_muiInfo.hinstLocRes != NULL && g_muiInfo.hinstLocRes != hinstOrg)
|
|
{
|
|
FreeLibrary(g_muiInfo.hinstLocRes);
|
|
|
|
g_muiInfo.hinstLocRes = NULL;
|
|
g_muiInfo.fLoaded = FALSE;
|
|
}
|
|
|
|
if (g_hVersion != NULL)
|
|
{
|
|
FreeLibrary(g_hVersion);
|
|
g_hVersion = NULL;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiClearResource
|
|
//
|
|
// Safe to call from dll detach.
|
|
// Call this routine to free all static resources.
|
|
// Must call MuiLoadReource again before using mui apis.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MuiClearResource()
|
|
{
|
|
g_csMuiLib.Delete();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiFreeResource
|
|
//
|
|
// Not safe to call from dll detach -- libraries may be freed.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MuiFreeResource(HINSTANCE hinstOrg)
|
|
{
|
|
MuiFlushDlls(hinstOrg);
|
|
MuiClearResource();
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiGetHinstance
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HINSTANCE MuiGetHinstance()
|
|
{
|
|
MuiResAssure();
|
|
|
|
return g_muiInfo.hinstLocRes;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiLoadLibrary
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HINSTANCE MuiLoadLibrary(LPCTSTR lpLibFileName, HMODULE hModule)
|
|
{
|
|
HINSTANCE hResInst = NULL;
|
|
TCHAR szTemp[10];
|
|
TCHAR szMuiPath[MAX_PATH * 2];
|
|
TCHAR szOrgDllPath[MAX_PATH];
|
|
TCHAR szMuiVerStr[MAX_PATH];
|
|
TCHAR szOrgVerStr[MAX_PATH];
|
|
LPCTSTR lpMuiPath = NULL;
|
|
LANGID langid;
|
|
UINT uSize = 0;
|
|
|
|
|
|
EnterCriticalSection(g_csMuiLib);
|
|
|
|
langid = GetPlatformResourceLangID();
|
|
|
|
// 409 is default resource langid in base dll, so we can skip the extra work
|
|
if (langid == 0x0409)
|
|
goto Exit;
|
|
|
|
if (hModule)
|
|
{
|
|
if (GetWindowsDirectory(szMuiPath, MAX_PATH))
|
|
{
|
|
StringCchCat(szMuiPath, ARRAYSIZE(szMuiPath), c_szMuiDir);
|
|
StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%04x\\"), langid);
|
|
StringCchCat(szMuiPath, ARRAYSIZE(szMuiPath), szTemp);
|
|
StringCchCat(szMuiPath, ARRAYSIZE(szMuiPath), lpLibFileName);
|
|
StringCchCat(szMuiPath, ARRAYSIZE(szMuiPath), c_szMuiExt);
|
|
|
|
if (lstrlen(szMuiPath) >= MAX_PATH*2)
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
if (hModule)
|
|
{
|
|
//
|
|
// Get current full file path.
|
|
//
|
|
GetModuleFileName(hModule, szOrgDllPath, ARRAYSIZE(szOrgDllPath));
|
|
}
|
|
else
|
|
{
|
|
*szOrgDllPath = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
if (!(GetFileVersionString(szMuiPath, szMuiVerStr, ARRAYSIZE(szMuiVerStr)) &&
|
|
GetFileVersionString(szOrgDllPath, szOrgVerStr, ARRAYSIZE(szOrgVerStr))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Checking the major version and ignore the minor version
|
|
//
|
|
if (strncmp(szMuiVerStr, szOrgVerStr, VERSION_MINOR_INDEX) != 0)
|
|
goto Exit;
|
|
|
|
if (!hResInst)
|
|
{
|
|
//hResInst = LoadLibraryEx(szMuiPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
|
hResInst = LoadLibrary(szMuiPath);
|
|
}
|
|
|
|
Exit:
|
|
g_muiInfo.fLoaded = TRUE;
|
|
|
|
LeaveCriticalSection(g_csMuiLib);
|
|
|
|
return hResInst;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiLoadString
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int MuiLoadString(HINSTANCE hinstOrg, UINT uID, LPSTR lpBuffer, INT nBufferMax)
|
|
{
|
|
|
|
LPWSTR lpWCBuf;
|
|
UINT cch = 0;
|
|
|
|
lpWCBuf = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * (nBufferMax + 1));
|
|
|
|
if (lpWCBuf && MuiLoadStringWrapW(hinstOrg, uID, lpWCBuf, nBufferMax))
|
|
{
|
|
cch = WideCharToMultiByte(g_muiInfo.dwCodePage, NULL, lpWCBuf, -1, lpBuffer, nBufferMax, NULL, NULL);
|
|
}
|
|
|
|
if (lpWCBuf)
|
|
LocalFree(lpWCBuf);
|
|
|
|
return cch;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiLoadStringWrapW
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int MuiLoadStringWrapW(HINSTANCE hinstOrg, UINT uID, LPWSTR lpBuffer, UINT nBufferMax)
|
|
{
|
|
HINSTANCE hinstLocRes;
|
|
|
|
MuiResAssure();
|
|
|
|
if (g_muiInfo.hinstLocRes && g_muiInfo.hinstOrg == hinstOrg)
|
|
hinstLocRes = g_muiInfo.hinstLocRes;
|
|
else
|
|
hinstLocRes = hinstOrg;
|
|
|
|
if (nBufferMax <= 0) return 0; // sanity check
|
|
|
|
PWCHAR pwch;
|
|
|
|
/*
|
|
* String tables are broken up into "bundles" of 16 strings each.
|
|
*/
|
|
HRSRC hrsrc;
|
|
int cwch = 0;
|
|
|
|
hrsrc = FindResourceA(hinstLocRes, (LPSTR)(LONG_PTR)(1 + uID / 16), (LPSTR)RT_STRING);
|
|
if (hrsrc) {
|
|
pwch = (PWCHAR)LoadResource(hinstLocRes, hrsrc);
|
|
if (pwch) {
|
|
/*
|
|
* Now skip over the strings in the resource until we
|
|
* hit the one we want. Each entry is a counted string,
|
|
* just like Pascal.
|
|
*/
|
|
for (uID %= 16; uID; uID--) {
|
|
pwch += *pwch + 1;
|
|
}
|
|
cwch = min(*pwch, nBufferMax - 1);
|
|
memcpy(lpBuffer, pwch+1, cwch * sizeof(WCHAR)); /* Copy the goo */
|
|
}
|
|
}
|
|
lpBuffer[cwch] = L'\0'; /* Terminate the string */
|
|
return cwch;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MuiDialogBoxParam
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR MuiDialogBoxParam(
|
|
HINSTANCE hInstance,
|
|
LPCTSTR lpTemplateName,
|
|
HWND hwndParent,
|
|
DLGPROC lpDialogFunc,
|
|
LPARAM dwInitParam)
|
|
{
|
|
HRSRC hrsr;
|
|
HGLOBAL hGlobal;
|
|
LPDLGTEMPLATE pTemplate;
|
|
INT_PTR iRet = -1;
|
|
HINSTANCE hMuiInstance;
|
|
|
|
if (!IsOnNT51() && g_muiInfo.hinstLocRes)
|
|
hMuiInstance = g_muiInfo.hinstLocRes;
|
|
else
|
|
hMuiInstance = hInstance;
|
|
|
|
if (hrsr = FindResource(hMuiInstance, lpTemplateName, RT_DIALOG))
|
|
{
|
|
if (hGlobal = LoadResource(hMuiInstance, hrsr))
|
|
{
|
|
if (pTemplate = (LPDLGTEMPLATE)LockResource(hGlobal))
|
|
{
|
|
if(IsOnNT())
|
|
iRet = DialogBoxIndirectParamW(hMuiInstance, pTemplate, hwndParent, lpDialogFunc, dwInitParam);
|
|
else
|
|
iRet = DialogBoxIndirectParamA(hMuiInstance, pTemplate, hwndParent, lpDialogFunc, dwInitParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// EnumLangProc
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
BOOL
|
|
CALLBACK
|
|
EnumLangProc(
|
|
HANDLE hModule, // resource-module handle
|
|
LPCTSTR lpszType, // pointer to resource type
|
|
LPCTSTR lpszName, // pointer to resource name
|
|
WORD wIDLanguage, // resource language identifier
|
|
LONG_PTR lParam // application-defined parameter
|
|
)
|
|
{
|
|
ENUMLANGDATA *pLangData;
|
|
|
|
pLangData = (ENUMLANGDATA *) lParam;
|
|
|
|
//
|
|
// for localized build contains multiple resource,
|
|
// it usually contains 0409 as backup lang.
|
|
//
|
|
// if LangInfo->LangID != 0 means we already assigned an ID to it
|
|
//
|
|
// so when wIDLanguage == 0x409, we keep the one we got from last time
|
|
//
|
|
if ((wIDLanguage == 0x409) && (pLangData->fFoundLang)) {
|
|
return TRUE;
|
|
}
|
|
|
|
pLangData->langid = wIDLanguage;
|
|
pLangData->fFoundLang = TRUE;
|
|
|
|
return TRUE; // continue enumeration
|
|
}
|
|
|
|
const TCHAR c_szKeyResLocale[] = TEXT(".Default\\Control Panel\\desktop\\ResourceLocale");
|
|
const TCHAR c_szNlsLocale[] = TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale");
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetPlatformResourceLangID
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LANGID GetPlatformResourceLangID(void)
|
|
{
|
|
static LANGID langRes = 0;
|
|
|
|
// we do this only once
|
|
if (langRes == 0)
|
|
{
|
|
LANGID langidTemp = 0;
|
|
if (IsOnNT5()) // w2k or above
|
|
{
|
|
HMODULE hmod = GetSystemModuleHandle(TEXT("KERNEL32"));
|
|
FARPROC pfn = NULL;
|
|
if (hmod)
|
|
{
|
|
pfn = GetProcAddress(hmod, "GetUserDefaultUILanguage");
|
|
}
|
|
|
|
if (pfn)
|
|
langidTemp = (LANGID) pfn();
|
|
|
|
}
|
|
else if (IsOnNT())
|
|
{
|
|
ENUMLANGDATA LangData = {0};
|
|
HMODULE hmod = GetSystemModuleHandle(TEXT("ntdll.dll"));
|
|
|
|
if (hmod)
|
|
{
|
|
EnumResourceLanguages(
|
|
hmod,
|
|
(LPCTSTR) RT_VERSION,
|
|
(LPCTSTR) UIntToPtr(1),
|
|
(ENUMRESLANGPROC)EnumLangProc,
|
|
(LONG_PTR)&LangData );
|
|
|
|
langidTemp = LangData.langid;
|
|
}
|
|
|
|
}
|
|
else if (IsOn95() || IsOn98()) // win9x, Me
|
|
{
|
|
HKEY hkey = NULL;
|
|
DWORD dwCnt;
|
|
TCHAR szLocale[128];
|
|
|
|
|
|
dwCnt = ARRAYSIZE(szLocale);
|
|
|
|
if (ERROR_SUCCESS
|
|
== RegOpenKeyEx(HKEY_USERS, c_szKeyResLocale, 0, KEY_READ, &hkey))
|
|
{
|
|
if (ERROR_SUCCESS==RegQueryValueEx(hkey, NULL, NULL, NULL, (LPBYTE)szLocale, &dwCnt))
|
|
{
|
|
langidTemp = (LANGID)AsciiToNum(szLocale);
|
|
}
|
|
}
|
|
else if (ERROR_SUCCESS
|
|
== RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szNlsLocale, 0, KEY_READ, &hkey))
|
|
{
|
|
if (ERROR_SUCCESS==RegQueryValueEx(hkey, NULL, NULL, NULL, (LPBYTE)szLocale, &dwCnt))
|
|
{
|
|
langidTemp = (LANGID)AsciiToNum(szLocale);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
if (!langidTemp)
|
|
{
|
|
langidTemp = GetSystemDefaultLangID();
|
|
}
|
|
|
|
EnterCriticalSection(g_csMuiLib);
|
|
|
|
langRes = langidTemp;
|
|
|
|
LeaveCriticalSection(g_csMuiLib);
|
|
}
|
|
return langRes;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetFileVersionString
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL GetFileVersionString(LPTSTR pszFileName, LPTSTR pszVerStr, UINT uVerStrLen)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
DWORD dwVerHandle;
|
|
DWORD dwVerInfoSize;
|
|
LPVOID lpVerData = NULL;
|
|
LANGID langid;
|
|
|
|
// for perf, since we only execute this code once or zero times
|
|
// per process, we'll do an explicit LoadLibrary instead of
|
|
// statically linking
|
|
if (g_hVersion == NULL)
|
|
{
|
|
if ((g_hVersion = LoadSystemLibrary(TEXT("version.dll"))) == NULL)
|
|
return FALSE;
|
|
|
|
g_VersionFuncTbl.pfnGetFileVersionInfo = (PFNGETFILEVERSIONINFO)GetProcAddress(g_hVersion, TEXT("GetFileVersionInfoA"));
|
|
g_VersionFuncTbl.pfnGetFileVersionInfoSize = (PFNGETFILEVERSIONINFOSIZE)GetProcAddress(g_hVersion, TEXT("GetFileVersionInfoSizeA"));
|
|
g_VersionFuncTbl.pfnVerQueryValue = (PFNVERQUERYVALUE)GetProcAddress(g_hVersion, TEXT("VerQueryValueA"));
|
|
}
|
|
|
|
if (g_VersionFuncTbl.pfnGetFileVersionInfo == NULL ||
|
|
g_VersionFuncTbl.pfnGetFileVersionInfoSize == NULL ||
|
|
g_VersionFuncTbl.pfnVerQueryValue == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
langid = GetPlatformResourceLangID();
|
|
|
|
dwVerInfoSize = g_VersionFuncTbl.pfnGetFileVersionInfoSize(pszFileName, &dwVerHandle);
|
|
|
|
if (dwVerInfoSize)
|
|
{
|
|
int i;
|
|
UINT cbTranslate;
|
|
UINT cchVer = 0;
|
|
LPDWORD lpTranslate;
|
|
LPTSTR lpszVer = NULL;
|
|
TCHAR szVerName[MAX_PATH];
|
|
|
|
lpVerData = LocalAlloc(LPTR, dwVerInfoSize);
|
|
|
|
g_VersionFuncTbl.pfnGetFileVersionInfo(pszFileName, dwVerHandle, dwVerInfoSize, lpVerData);
|
|
|
|
szVerName[0] = TEXT('\0');
|
|
|
|
if (g_VersionFuncTbl.pfnVerQueryValue(lpVerData, (LPTSTR)c_szVerTranslate, (LPVOID*)&lpTranslate, &cbTranslate))
|
|
{
|
|
cbTranslate /= sizeof(DWORD);
|
|
|
|
for (i = 0; (UINT) i < cbTranslate; i++)
|
|
{
|
|
if (LOWORD(*(lpTranslate + i)) == langid)
|
|
{
|
|
StringCchPrintf(szVerName, ARRAYSIZE(szVerName), TEXT("\\StringFileInfo\\%04X%04X\\"), LOWORD(*(lpTranslate + i)), HIWORD(*(lpTranslate + i)));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (szVerName[0] == TEXT('\0'))
|
|
{
|
|
StringCchCopy(szVerName, ARRAYSIZE(szVerName), TEXT("\\StringFileInfo\\040904B0\\"));
|
|
}
|
|
|
|
StringCchCat(szVerName, ARRAYSIZE(szVerName), TEXT("FileVersion"));
|
|
|
|
if (g_VersionFuncTbl.pfnVerQueryValue(lpVerData, szVerName, (LPVOID*)&lpszVer, &cchVer))
|
|
{
|
|
StringCchCopy(pszVerStr, uVerStrLen, lpszVer);
|
|
*(pszVerStr + VERSIONSIZE) = TEXT('\0');
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
if (lpVerData)
|
|
LocalFree((HANDLE)lpVerData);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetUIACP
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD GetUIACP()
|
|
{
|
|
if (!(g_muiInfo.dwCodePage))
|
|
{
|
|
LANGID langRes = 0;
|
|
|
|
langRes = GetPlatformResourceLangID();
|
|
|
|
GetLocaleInfo(MAKELCID(langRes, SORT_DEFAULT),
|
|
LOCALE_IDEFAULTANSICODEPAGE,
|
|
g_muiInfo.szCodePage,
|
|
ARRAYSIZE(g_muiInfo.szCodePage));
|
|
|
|
if (!AsciiToNumDec(g_muiInfo.szCodePage, &g_muiInfo.dwCodePage))
|
|
{
|
|
g_muiInfo.dwCodePage = GetACP();
|
|
}
|
|
}
|
|
|
|
if (IsValidCodePage(g_muiInfo.dwCodePage) == 0)
|
|
g_muiInfo.dwCodePage = GetACP();
|
|
|
|
return g_muiInfo.dwCodePage;
|
|
}
|