From 652dfd43d603c33bc0be3bc0c849708d7e064a59 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 12 Aug 2018 01:20:20 +0200 Subject: Windows Installer: implement language selection mechanism at the start of the installer to make easier for international users. --- src/Common/Language.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) (limited to 'src/Common/Language.c') diff --git a/src/Common/Language.c b/src/Common/Language.c index 092bef48..bcf7b72f 100644 --- a/src/Common/Language.c +++ b/src/Common/Language.c @@ -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) -- cgit v1.2.3