mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 19:08:26 -06:00
Windows Installer: implement language selection mechanism at the start of the installer to make easier for international users.
This commit is contained in:
@@ -383,6 +383,208 @@ BOOL LoadLanguageFile ()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LoadLanguageFromResource (int resourceid, BOOL bSetPreferredLanguage, BOOL bForceSilent)
|
||||
{
|
||||
DWORD size;
|
||||
BYTE *res;
|
||||
char *xml, *header, *headerPtr;
|
||||
char langId[16] = "en", attr[32768], key[128];
|
||||
BOOL defaultLangParsed = FALSE, langFound = FALSE;
|
||||
WCHAR wattr[32768];
|
||||
int i, intKey, len;
|
||||
|
||||
#ifdef TCMOUNT
|
||||
int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_MOUNT_RSRC_HEADER, 0 };
|
||||
#endif
|
||||
|
||||
#ifdef VOLFORMAT
|
||||
int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_FORMAT_RSRC_HEADER, 0 };
|
||||
#endif
|
||||
|
||||
#ifdef SETUP
|
||||
int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_SETUP_RSRC_HEADER, 0 };
|
||||
#endif
|
||||
|
||||
res = (char*) MapResource (L"Languages", resourceid, &size);
|
||||
if (!res)
|
||||
return FALSE;
|
||||
|
||||
LocalizationActive = FALSE;
|
||||
ActiveLangPackVersion[0] = 0;
|
||||
ClearDictionaryPool ();
|
||||
|
||||
xml = res;
|
||||
xml = XmlFindElement (xml, "localization");
|
||||
if (!xml)
|
||||
return FALSE;
|
||||
|
||||
// Required VeraCrypt version
|
||||
XmlGetAttributeText (xml, "prog-version", attr, sizeof (attr));
|
||||
|
||||
// Search language id in language file
|
||||
while (xml = XmlFindElement (xml, "language"))
|
||||
{
|
||||
XmlGetAttributeText (xml, "langid", attr, sizeof (attr));
|
||||
if (strlen (attr))
|
||||
{
|
||||
StringCbCopyA (langId, sizeof (langId), attr);
|
||||
XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
|
||||
langFound = TRUE;
|
||||
break;
|
||||
}
|
||||
xml++;
|
||||
}
|
||||
|
||||
if (!langFound) return FALSE;
|
||||
|
||||
// Create font dictionary
|
||||
xml = (char *) res;
|
||||
while (xml = XmlFindElement (xml, "font"))
|
||||
{
|
||||
XmlGetAttributeText (xml, "lang", attr, sizeof (attr));
|
||||
if (strcmp (attr, langId) == 0)
|
||||
{
|
||||
Font font;
|
||||
memset (&font, 0, sizeof (font));
|
||||
|
||||
XmlGetAttributeText (xml, "face", attr, sizeof (attr));
|
||||
|
||||
len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
|
||||
font.FaceName = AddPoolData ((void *) wattr, len * 2);
|
||||
|
||||
XmlGetAttributeText (xml, "size", attr, sizeof (attr));
|
||||
sscanf (attr, "%d", &font.Size);
|
||||
|
||||
StringCbCopyA (attr, sizeof(attr), "font_");
|
||||
XmlGetAttributeText (xml, "class", attr + 5, sizeof (attr) - 5);
|
||||
AddDictionaryEntry (
|
||||
AddPoolData ((void *) attr, strlen (attr) + 1), 0,
|
||||
AddPoolData ((void *) &font, sizeof(font)));
|
||||
}
|
||||
|
||||
xml++;
|
||||
}
|
||||
|
||||
xml = (char *) res;
|
||||
while (xml = XmlFindElement (xml, "entry"))
|
||||
{
|
||||
void *key;
|
||||
void *text;
|
||||
|
||||
XmlGetAttributeText (xml, "lang", attr, sizeof (attr));
|
||||
if (strcmp (attr, langId) == 0)
|
||||
{
|
||||
if (XmlGetAttributeText (xml, "key", attr, sizeof (attr)))
|
||||
{
|
||||
key = AddPoolData (attr, strlen (attr) + 1);
|
||||
if (key == NULL) return FALSE;
|
||||
|
||||
XmlGetNodeText (xml, attr, sizeof (attr));
|
||||
|
||||
// Parse \ escape sequences
|
||||
{
|
||||
char *in = attr, *out = attr;
|
||||
while (*in)
|
||||
{
|
||||
if (*in == '\\')
|
||||
{
|
||||
in++;
|
||||
switch (*in++)
|
||||
{
|
||||
case '\\': *out++ = '\\'; break;
|
||||
case 't': *out++ = '\t'; break;
|
||||
case 'n': *out++ = 13; *out++ = 10; break;
|
||||
default:
|
||||
if (!bForceSilent)
|
||||
MessageBoxA (0, key, "VeraCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
*out++ = *in++;
|
||||
}
|
||||
*out = 0;
|
||||
}
|
||||
|
||||
// UTF8 => wide char
|
||||
len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
|
||||
if (len == 0)
|
||||
{
|
||||
if (!bForceSilent)
|
||||
MessageBoxA (0, key, "VeraCrypt: Error while decoding UTF-8 string", MB_ICONERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Add to dictionary
|
||||
text = AddPoolData ((void *) wattr, len * 2);
|
||||
if (text == NULL) return FALSE;
|
||||
|
||||
AddDictionaryEntry ((char *) key, 0, text);
|
||||
}
|
||||
}
|
||||
|
||||
xml++;
|
||||
}
|
||||
|
||||
defaultLangParsed = TRUE;
|
||||
|
||||
LocalizationActive = strcmp (langId, "en") != 0;
|
||||
LocalizationSerialNo++;
|
||||
|
||||
if (bSetPreferredLanguage)
|
||||
StringCbCopyA (PreferredLangId, sizeof (PreferredLangId), langId);
|
||||
|
||||
// Create control ID dictionary
|
||||
|
||||
// Default controls
|
||||
AddDictionaryEntry (NULL, 1, GetString ("IDOK"));
|
||||
AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL"));
|
||||
AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE"));
|
||||
AddDictionaryEntry (NULL, 9, GetString ("IDHELP"));
|
||||
|
||||
for (i = 0; headers[i] != 0; i++)
|
||||
{
|
||||
if (HeaderResource[i] == NULL)
|
||||
{
|
||||
HeaderResource[i] = MapResource (L"Header", headers[i], &size);
|
||||
if (HeaderResource[i])
|
||||
HeaderResourceSize[i] = size;
|
||||
}
|
||||
|
||||
headerPtr = NULL;
|
||||
if (HeaderResource[i])
|
||||
{
|
||||
headerPtr = (char*) malloc (HeaderResourceSize[i] + 1);
|
||||
if (headerPtr)
|
||||
{
|
||||
memcpy (headerPtr, HeaderResource[i], HeaderResourceSize[i]);
|
||||
headerPtr [HeaderResourceSize[i]] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
header = headerPtr;
|
||||
if (header == NULL) return FALSE;
|
||||
header--;
|
||||
|
||||
do
|
||||
{
|
||||
header++;
|
||||
if (sscanf (header, "#define %127s %d", key, &intKey) == 2)
|
||||
{
|
||||
WCHAR *str = GetString (key);
|
||||
|
||||
if (str != UnknownString)
|
||||
AddDictionaryEntry (NULL, intKey, str);
|
||||
}
|
||||
|
||||
} while ((header = strchr (header, '\n')) != NULL);
|
||||
|
||||
free (headerPtr);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// lParam = 1: auto mode
|
||||
BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
Reference in New Issue
Block a user