1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-11 11:08:02 -06:00

Windows: code enhancements for language selection mechanism in the installer.

This commit is contained in:
Mounir IDRASSI
2018-08-13 14:52:52 +02:00
parent 68fe28af42
commit 17af27bc7f
3 changed files with 131 additions and 268 deletions

View File

@@ -44,6 +44,7 @@ static DWORD LanguageResourceSize = 0;
static char *HeaderResource[2] = {NULL, NULL}; static char *HeaderResource[2] = {NULL, NULL};
static DWORD HeaderResourceSize[2] = {0, 0}; static DWORD HeaderResourceSize[2] = {0, 0};
static char ActiveLangPackVersion[6] = {0}; static char ActiveLangPackVersion[6] = {0};
static int LanguageResourceId = 0;
static char *MapFirstLanguageFile () static char *MapFirstLanguageFile ()
{ {
@@ -59,6 +60,8 @@ static char *MapFirstLanguageFile ()
LanguageFileBuffer = NULL; LanguageFileBuffer = NULL;
} }
LanguageResourceId = 0;
if (LanguageResource == NULL) if (LanguageResource == NULL)
{ {
DWORD size; 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; wchar_t f[TC_MAX_PATH*2], *t;
WIN32_FIND_DATAW find; WIN32_FIND_DATAW find;
@@ -96,6 +99,8 @@ static char *MapNextLanguageFile ()
LanguageFileBuffer = NULL; LanguageFileBuffer = NULL;
} }
if (resourceid == 0)
{
if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) if (LanguageFileFindHandle == INVALID_HANDLE_VALUE)
{ {
GetModuleFileNameW (NULL, f, sizeof (f) / sizeof (f[0])); GetModuleFileNameW (NULL, f, sizeof (f) / sizeof (f[0]));
@@ -151,12 +156,33 @@ static char *MapNextLanguageFile ()
} }
LanguageFileBuffer [find.nFileSizeLow] = 0; // we have allocated (find.nFileSizeLow + 1) bytes 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;
if (LanguageResource)
{
LanguageFileBuffer = malloc(LanguageResourceSize + 1);
if (LanguageFileBuffer)
{
memcpy (LanguageFileBuffer, LanguageResource, LanguageResourceSize);
LanguageFileBuffer[LanguageResourceSize] = 0;
}
}
}
return LanguageFileBuffer; return LanguageFileBuffer;
} }
BOOL LoadLanguageFile () static BOOL LoadLanguageData (int resourceid, BOOL bForceSetPreferredLanguage, BOOL bForceSilent)
{ {
DWORD size; DWORD size;
BYTE *res; BYTE *res;
@@ -184,11 +210,11 @@ BOOL LoadLanguageFile ()
ActiveLangPackVersion[0] = 0; ActiveLangPackVersion[0] = 0;
ClearDictionaryPool (); ClearDictionaryPool ();
if (PreferredLangId[0] != 0) if ((resourceid == 0) && (PreferredLangId[0] != 0))
StringCbCopyA (langId, sizeof(langId), PreferredLangId); StringCbCopyA (langId, sizeof(langId), PreferredLangId);
// Parse all available language files until preferred language is found // 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 = (char *) res;
xml = XmlFindElement (xml, "localization"); xml = XmlFindElement (xml, "localization");
@@ -203,6 +229,7 @@ BOOL LoadLanguageFile ()
{ {
wchar_t m[2048]; 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); 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);
if (!bForceSilent)
MessageBoxW (NULL, m, L"VeraCrypt", MB_ICONERROR); MessageBoxW (NULL, m, L"VeraCrypt", MB_ICONERROR);
continue; continue;
} }
@@ -213,6 +240,8 @@ BOOL LoadLanguageFile ()
while (xml = XmlFindElement (xml, "language")) while (xml = XmlFindElement (xml, "language"))
{ {
XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); XmlGetAttributeText (xml, "langid", attr, sizeof (attr));
if (resourceid == 0)
{
if (strcmp (attr, langId) == 0) if (strcmp (attr, langId) == 0)
{ {
XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion)); XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
@@ -221,6 +250,14 @@ BOOL LoadLanguageFile ()
} }
xml++; xml++;
} }
else
{
StringCbCopyA (langId, sizeof (langId), attr);
XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
langFound = TRUE;
break;
}
}
if (!langFound) continue; if (!langFound) continue;
} }
@@ -288,6 +325,7 @@ BOOL LoadLanguageFile ()
case 't': *out++ = '\t'; break; case 't': *out++ = '\t'; break;
case 'n': *out++ = 13; *out++ = 10; break; case 'n': *out++ = 13; *out++ = 10; break;
default: default:
if (!bForceSilent)
MessageBoxA (0, key, "VeraCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR); MessageBoxA (0, key, "VeraCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR);
return FALSE; return FALSE;
} }
@@ -302,6 +340,7 @@ BOOL LoadLanguageFile ()
len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
if (len == 0) if (len == 0)
{ {
if (!bForceSilent)
MessageBoxA (0, key, "VeraCrypt: Error while decoding UTF-8 string", MB_ICONERROR); MessageBoxA (0, key, "VeraCrypt: Error while decoding UTF-8 string", MB_ICONERROR);
return FALSE; return FALSE;
} }
@@ -324,7 +363,7 @@ BOOL LoadLanguageFile ()
if (!defaultLangParsed) if (!defaultLangParsed)
{ {
defaultLangParsed = TRUE; defaultLangParsed = TRUE;
if (langId[0] == 0 || strcmp (langId, "en") == 0) if ((resourceid == 0) && (langId[0] == 0 || strcmp (langId, "en") == 0))
break; break;
} }
} }
@@ -332,206 +371,7 @@ BOOL LoadLanguageFile ()
LocalizationActive = langFound && strcmp (langId, "en") != 0; LocalizationActive = langFound && strcmp (langId, "en") != 0;
LocalizationSerialNo++; LocalizationSerialNo++;
// Create control ID dictionary if (bForceSetPreferredLanguage)
// 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;
}
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); StringCbCopyA (PreferredLangId, sizeof (PreferredLangId), langId);
// Create control ID dictionary // Create control ID dictionary
@@ -585,6 +425,15 @@ BOOL LoadLanguageFromResource (int resourceid, BOOL bSetPreferredLanguage, BOOL
return TRUE; return TRUE;
} }
BOOL LoadLanguageFile ()
{
return LoadLanguageData (0, FALSE, FALSE);
}
BOOL LoadLanguageFromResource (int resourceid, BOOL bSetPreferredLanguage, BOOL bForceSilent)
{
return LoadLanguageData (resourceid, bSetPreferredLanguage, bForceSilent);
}
// lParam = 1: auto mode // lParam = 1: auto mode
BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 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"); LocalizeDialog (hwndDlg, "IDD_LANGUAGE");
ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS); 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")) while (xml = XmlFindElement (xml, "language"))
{ {

View File

@@ -2414,10 +2414,15 @@ static void UpdateSelectLanguageDialog (HWND hwndDlg)
HWND hLangList = GetDlgItem (hwndDlg, IDC_LANGUAGES_LIST); HWND hLangList = GetDlgItem (hwndDlg, IDC_LANGUAGES_LIST);
LPARAM nIndex = SendMessage (hLangList, CB_GETCURSEL, 0, 0); LPARAM nIndex = SendMessage (hLangList, CB_GETCURSEL, 0, 0);
int resourceid = (int) SendMessage (hLangList, CB_GETITEMDATA, nIndex, 0); int resourceid = (int) SendMessage (hLangList, CB_GETITEMDATA, nIndex, 0);
BOOL bVal;
LoadLanguageFromResource (resourceid, TRUE, TRUE); LoadLanguageFromResource (resourceid, TRUE, TRUE);
bVal = LocalizationActive;
LocalizationActive = TRUE;
LocalizeDialog (hwndDlg, "IDD_INSTL_DLG"); LocalizeDialog (hwndDlg, "IDD_INSTL_DLG");
InvalidateRect (hwndDlg, NULL, FALSE);
LocalizationActive = bVal;
} }
BOOL CALLBACK SelectLanguageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) BOOL CALLBACK SelectLanguageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -2660,7 +2665,15 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz
{ {
if (!bDevm && !LocalizationActive && (nCurrentOS >= WIN_VISTA)) if (!bDevm && !LocalizationActive && (nCurrentOS >= WIN_VISTA))
{ {
DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_INSTALL_LANGUAGE), NULL, (DLGPROC) SelectLanguageDialogProc, (LPARAM) 0 ); BOOL bHasPreferredLanguage = (strlen (GetPreferredLangId ()) > 0)? TRUE : FALSE;
if ((IDCANCEL == DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_INSTALL_LANGUAGE), NULL, (DLGPROC) SelectLanguageDialogProc, (LPARAM) 0 ))
&& !bHasPreferredLanguage
)
{
// Language dialog cancelled by user: exit the installer
FinalizeApp ();
exit (1);
}
} }
/* Create the main dialog for install */ /* Create the main dialog for install */

View File

@@ -205,18 +205,19 @@ BEGIN
PUSHBUTTON "Donate now...",IDC_DONATE,124,94,96,14 PUSHBUTTON "Donate now...",IDC_DONATE,124,94,96,14
END END
IDD_INSTALL_LANGUAGE DIALOGEX 0, 0, 213, 87 IDD_INSTALL_LANGUAGE DIALOGEX 0, 0, 214, 75
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "VeraCrypt Setup Wizard" CAPTION "VeraCrypt Setup Wizard"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "OK",IDOK,102,66,50,14 DEFPUSHBUTTON "OK",IDOK,102,54,50,14
PUSHBUTTON "Cancel",IDCANCEL,156,66,50,14 PUSHBUTTON "Cancel",IDCANCEL,157,54,50,14
ICON 501,IDC_STATIC,10,10,32,32 ICON IDI_SETUP,IDC_STATIC,10,10,32,32
LTEXT "Select the language to use during the installation:",IDC_SELECT_LANGUAGE_LABEL,42,13,157,26 LTEXT "Select the language to use during the installation:",IDC_SELECT_LANGUAGE_LABEL,42,13,158,17
COMBOBOX IDC_LANGUAGES_LIST,42,44,164,155,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_LANGUAGES_LIST,42,36,164,155,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
END END
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Icon // Icon
@@ -334,9 +335,9 @@ BEGIN
IDD_INSTALL_LANGUAGE, DIALOG IDD_INSTALL_LANGUAGE, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 206 RIGHTMARGIN, 207
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 80 BOTTOMMARGIN, 68
END END
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED