From 17af27bc7fa82030084c3c3065f9516bfb88a899 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 13 Aug 2018 14:52:52 +0200 Subject: Windows: code enhancements for language selection mechanism in the installer. --- src/Common/Language.c | 357 +++++++++++++++----------------------------------- 1 file changed, 103 insertions(+), 254 deletions(-) (limited to 'src/Common/Language.c') diff --git a/src/Common/Language.c b/src/Common/Language.c index bcf7b72f..ba0b6d19 100644 --- a/src/Common/Language.c +++ b/src/Common/Language.c @@ -44,6 +44,7 @@ static DWORD LanguageResourceSize = 0; static char *HeaderResource[2] = {NULL, NULL}; static DWORD HeaderResourceSize[2] = {0, 0}; static char ActiveLangPackVersion[6] = {0}; +static int LanguageResourceId = 0; static char *MapFirstLanguageFile () { @@ -59,6 +60,8 @@ static char *MapFirstLanguageFile () LanguageFileBuffer = NULL; } + LanguageResourceId = 0; + if (LanguageResource == NULL) { DWORD size; @@ -81,7 +84,7 @@ static char *MapFirstLanguageFile () } -static char *MapNextLanguageFile () +static char *MapNextLanguageFile (int resourceid) { wchar_t f[TC_MAX_PATH*2], *t; WIN32_FIND_DATAW find; @@ -96,67 +99,90 @@ static char *MapNextLanguageFile () LanguageFileBuffer = NULL; } - if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) + if (resourceid == 0) { - GetModuleFileNameW (NULL, f, sizeof (f) / sizeof (f[0])); - t = wcsrchr (f, L'\\'); - if (t == NULL) return NULL; + if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) + { + GetModuleFileNameW (NULL, f, sizeof (f) / sizeof (f[0])); + t = wcsrchr (f, L'\\'); + if (t == NULL) return NULL; - *t = 0; - StringCbCatW (f, sizeof(f), L"\\Languages\\Language*.xml"); + *t = 0; + StringCbCatW (f, sizeof(f), L"\\Languages\\Language*.xml"); - LanguageFileFindHandle = FindFirstFileW (f, &find); - } - else if (!FindNextFileW (LanguageFileFindHandle, &find)) - { - FindClose (LanguageFileFindHandle); - LanguageFileFindHandle = INVALID_HANDLE_VALUE; - return NULL; - } + LanguageFileFindHandle = FindFirstFileW (f, &find); + } + else if (!FindNextFileW (LanguageFileFindHandle, &find)) + { + FindClose (LanguageFileFindHandle); + LanguageFileFindHandle = INVALID_HANDLE_VALUE; + return NULL; + } - if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) return NULL; - if (find.nFileSizeHigh != 0) return NULL; + if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) return NULL; + if (find.nFileSizeHigh != 0) return NULL; - LanguageFileBuffer = malloc(find.nFileSizeLow + 1); - if (LanguageFileBuffer == NULL) return NULL; + LanguageFileBuffer = malloc(find.nFileSizeLow + 1); + if (LanguageFileBuffer == NULL) return NULL; - GetModuleFileNameW (NULL, f, sizeof (f) / sizeof(f[0])); - t = wcsrchr (f, L'\\'); - if (t == NULL) - { - free(LanguageFileBuffer); - LanguageFileBuffer = NULL; - return NULL; - } + GetModuleFileNameW (NULL, f, sizeof (f) / sizeof(f[0])); + t = wcsrchr (f, L'\\'); + if (t == NULL) + { + free(LanguageFileBuffer); + LanguageFileBuffer = NULL; + return NULL; + } - t[1] = 0; - StringCbCatW (f, sizeof(f), L"Languages\\"); - StringCbCatW (f, sizeof(f),find.cFileName); + t[1] = 0; + StringCbCatW (f, sizeof(f), L"Languages\\"); + StringCbCatW (f, sizeof(f),find.cFileName); - file = CreateFileW (f, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); - if (file == INVALID_HANDLE_VALUE) - { - free(LanguageFileBuffer); - LanguageFileBuffer = NULL; - return NULL; - } + file = CreateFileW (f, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file == INVALID_HANDLE_VALUE) + { + free(LanguageFileBuffer); + LanguageFileBuffer = NULL; + return NULL; + } - bStatus = ReadFile (file, LanguageFileBuffer, find.nFileSizeLow, &read, NULL); - CloseHandle (file); - if (!bStatus || (read != find.nFileSizeLow)) - { - free(LanguageFileBuffer); - LanguageFileBuffer = NULL; - return NULL; + bStatus = ReadFile (file, LanguageFileBuffer, find.nFileSizeLow, &read, NULL); + CloseHandle (file); + if (!bStatus || (read != find.nFileSizeLow)) + { + free(LanguageFileBuffer); + LanguageFileBuffer = NULL; + return NULL; + } + + LanguageFileBuffer [find.nFileSizeLow] = 0; // we have allocated (find.nFileSizeLow + 1) bytes } + else if (LanguageResourceId != resourceid) + { + DWORD size; + + LanguageResourceId = resourceid; + + LanguageResource = MapResource (L"Languages", LanguageResourceId, &size); + if (LanguageResource) + LanguageResourceSize = size; - LanguageFileBuffer [find.nFileSizeLow] = 0; // we have allocated (find.nFileSizeLow + 1) bytes + if (LanguageResource) + { + LanguageFileBuffer = malloc(LanguageResourceSize + 1); + if (LanguageFileBuffer) + { + memcpy (LanguageFileBuffer, LanguageResource, LanguageResourceSize); + LanguageFileBuffer[LanguageResourceSize] = 0; + } + } + } return LanguageFileBuffer; } -BOOL LoadLanguageFile () +static BOOL LoadLanguageData (int resourceid, BOOL bForceSetPreferredLanguage, BOOL bForceSilent) { DWORD size; BYTE *res; @@ -184,11 +210,11 @@ BOOL LoadLanguageFile () ActiveLangPackVersion[0] = 0; ClearDictionaryPool (); - if (PreferredLangId[0] != 0) + if ((resourceid == 0) && (PreferredLangId[0] != 0)) StringCbCopyA (langId, sizeof(langId), PreferredLangId); // Parse all available language files until preferred language is found - for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile ()) + for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile (resourceid)) { xml = (char *) res; xml = XmlFindElement (xml, "localization"); @@ -203,7 +229,8 @@ BOOL LoadLanguageFile () { wchar_t m[2048]; StringCbPrintfW (m, sizeof(m), L"The installed language pack is incompatible with this version of VeraCrypt (the language pack is for VeraCrypt %hs). A newer version may be available at www.idrix.fr.\n\nTo prevent this message from being displayed, do any of the following:\n\n- Select 'Settings' > 'Language'; then select 'English' and click 'OK'.\n\n- Remove or replace the language pack with a compatible version (the language pack may reside e.g. in 'C:\\Program Files\\VeraCrypt' or '%%LOCALAPPDATA%%\\VirtualStore\\Program Files\\VeraCrypt', etc.)", attr); - MessageBoxW (NULL, m, L"VeraCrypt", MB_ICONERROR); + if (!bForceSilent) + MessageBoxW (NULL, m, L"VeraCrypt", MB_ICONERROR); continue; } @@ -213,13 +240,23 @@ BOOL LoadLanguageFile () while (xml = XmlFindElement (xml, "language")) { XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); - if (strcmp (attr, langId) == 0) + if (resourceid == 0) + { + if (strcmp (attr, langId) == 0) + { + XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion)); + langFound = TRUE; + break; + } + xml++; + } + else { + StringCbCopyA (langId, sizeof (langId), attr); XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion)); langFound = TRUE; break; } - xml++; } if (!langFound) continue; @@ -288,7 +325,8 @@ BOOL LoadLanguageFile () case 't': *out++ = '\t'; break; case 'n': *out++ = 13; *out++ = 10; break; default: - MessageBoxA (0, key, "VeraCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR); + if (!bForceSilent) + MessageBoxA (0, key, "VeraCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR); return FALSE; } } @@ -302,7 +340,8 @@ BOOL LoadLanguageFile () len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); if (len == 0) { - MessageBoxA (0, key, "VeraCrypt: Error while decoding UTF-8 string", MB_ICONERROR); + if (!bForceSilent) + MessageBoxA (0, key, "VeraCrypt: Error while decoding UTF-8 string", MB_ICONERROR); return FALSE; } @@ -324,7 +363,7 @@ BOOL LoadLanguageFile () if (!defaultLangParsed) { defaultLangParsed = TRUE; - if (langId[0] == 0 || strcmp (langId, "en") == 0) + if ((resourceid == 0) && (langId[0] == 0 || strcmp (langId, "en") == 0)) break; } } @@ -332,6 +371,9 @@ BOOL LoadLanguageFile () LocalizationActive = langFound && strcmp (langId, "en") != 0; LocalizationSerialNo++; + if (bForceSetPreferredLanguage) + StringCbCopyA (PreferredLangId, sizeof (PreferredLangId), langId); + // Create control ID dictionary // Default controls @@ -383,208 +425,15 @@ BOOL LoadLanguageFile () return TRUE; } -BOOL LoadLanguageFromResource (int resourceid, BOOL bSetPreferredLanguage, BOOL bForceSilent) +BOOL LoadLanguageFile () { - 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; + return LoadLanguageData (0, FALSE, FALSE); } +BOOL LoadLanguageFromResource (int resourceid, BOOL bSetPreferredLanguage, BOOL bForceSilent) +{ + return LoadLanguageData (resourceid, bSetPreferredLanguage, bForceSilent); +} // lParam = 1: auto mode BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -606,7 +455,7 @@ BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa LocalizeDialog (hwndDlg, "IDD_LANGUAGE"); ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS); - for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile ()) + for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile (0)) { while (xml = XmlFindElement (xml, "language")) { -- cgit v1.2.3