VeraCrypt
aboutsummaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2020-07-02Language translations: Add newly added entry to the XML files of supported ↵Mounir IDRASSI39-0/+39
languages
2020-07-02Windows: Don't allow to encrypt the system drive if it is already encrypted ↵Mounir IDRASSI4-0/+117
by BitLocker
2020-07-02Windows: Replace GetSystemInfo calls by more reliable function to get number ↵Mounir IDRASSI2-16/+13
of CPUs active on the PC.
2020-07-02Windows: Don't use API for Processor Groups support if there is only 1 CPU ↵Mounir IDRASSI4-39/+84
group in the system. This can fix slowness issue observed on some PCs with AMD CPUs.
2020-07-02Linux/MacOSX: Allow choosing a filesystem other than FAT for outer volume ↵Mounir IDRASSI1-19/+43
but display warning about risks and implement an estimation of maximum possible size of hidden volume in this case.
2020-06-30XML Language files: update Chinese translationMounir IDRASSI1-2/+2
2020-06-30Language XML files: update Czech translation (contributed by Lagardere)Mounir IDRASSI1-2/+2
2020-06-29Increment internal version to 1.24.18 and update signed Windows drivers.Mounir IDRASSI15-17/+17
2020-06-29Windows: Fallback to Windows native formatting tool if we fail to format a ↵Mounir IDRASSI2-2/+153
volume as NTFS/exFAT/ReFS using FormatEx function from fmifs.dll
2020-06-29Language XML files: update Russian XML file by Dmitry Yerokhin.Mounir IDRASSI1-1/+1
2020-06-29Windows: Avoid displaying waiting dialog when /silent specified for ↵Mounir IDRASSI1-1/+1
"VeraCrypt Format" during creating of file container using /create switch and a filesystem other than FAT (fixes Github issue #648)
2020-06-28Language XML files: update Russian XML file by Dmitry Yerokhin.Mounir IDRASSI1-1/+1
2020-06-28Linux/MacOSX: Erase sensitive memory explicitly instead of relying on the ↵Mounir IDRASSI7-15/+5
compiler not optimizing calls to method Memory::Erase
2020-06-28Windows: Fix build error because of missing definition of the macro move_ptrMounir IDRASSI1-0/+4
2020-06-28Windows: Fix failure to detect suspension of machine that caused mounted ↵Mounir IDRASSI1-12/+47
volume not be dismount even if "Entering power saving mode" is checked in Preferences. This fix implements compatibility with Windows 10 Modern Standby and Windows 8.1 Connected Standby power model.
2020-06-28Windows: remove unused code targeting Windows 2000.Mounir IDRASSI7-77/+22
2020-06-26Language translations: Add newly added entry to the XML files of supported ↵Mounir IDRASSI38-0/+38
languages
2020-06-26Windows: Update signed driver to version 1.24.17Mounir IDRASSI6-3/+3
2020-06-26Update Language.nl.xml (#646)Thomas De Rocker1-0/+1
Update 1 string in Dutch language.
2020-06-26Update Language.xml (#645)Thomas De Rocker1-1/+1
fix typo
2020-06-26Linux/MacOSX: use standard std::shared_ptr instead of our custom ↵Mounir IDRASSI5-7/+30
implementation which is kept for compatibility with older compilers. We also introduce compatibility code for old compilers that don't define std::unique_ptr
2020-06-26Whirlpool: Remove unused "num" variable affectation in WHIRLPOOL_addMounir IDRASSI1-1/+0
2020-06-26Linux/MacOSX: fix warning reported by static code analysis tool about ↵Mounir IDRASSI2-3/+7
possible undefined output value in UserPreferences::SetValue and missing initialization of member variables in File constructor
2020-06-26Windows: fix warning reported by static code analyzed by adding copy ↵Mounir IDRASSI2-4/+32
constructor to _TEXT_EDIT_DIALOG_PARAM and = operator to HostDevice
2020-06-25Crypto: Fix random crash in Streebog in 32-bit, caused by use of aligned ↵Mounir IDRASSI1-8/+8
SSE2 instructions _mm_load_si128. Now we use _mm_loadu_si128 instead which is not slower than _mm_load_si128 on recent CPUs
2020-06-23Increment version to 1.24-Update7Mounir IDRASSI59-74/+96
2020-06-23Windows: Don't allow Hidden volume to have the same password, PIM and ↵Mounir IDRASSI2-7/+50
keyfiles as Outer volume
2020-06-23Linux/MacOSX: explicitely clear saved password from memory at last step of ↵Mounir IDRASSI1-0/+7
volume creation wizard
2020-06-23Linux/MacOSX: Use also PIM when comparing Outer and Hidden volumes credentialsMounir IDRASSI2-28/+64
2020-06-23Linux/MacOSX: take into account keyfiles when comparing Outer and Hidden ↵Mounir IDRASSI1-9/+31
volumes passwords
2020-06-23Linux/MacOSX: Don't allow Hidden volume to have the same password as Outer ↵Mounir IDRASSI2-0/+12
volume
2020-06-21Windows Driver: Use real disk sector size instead of generic 512 bytes value ↵Mounir IDRASSI1-4/+9
when probing disk real size
2020-06-21Linux/MacOSX: Read at least 32 bytes from /dev/random before allowing it to ↵Mounir IDRASSI2-3/+11
fail gracefully
2020-06-21Windows: support RAM encryption only if t1ha2 algorithm self test succeedsMounir IDRASSI1-1/+4
2020-06-21Windows: Fix issue when RAM encryption used, AES selected and AES-NI not ↵Mounir IDRASSI4-0/+20
supported by CPU that caused the free space of newly created volumes not filled with random data even if "quick format" is not selected by user.
2020-06-21Windows: call VcProtectKeys in benchmark warm-up when RAM encryption is ↵Mounir IDRASSI1-0/+4
enabled in order to be follow the same execution path as the result of benchmark calculations.
2020-06-19Linux/MacOSX: Don't always ignore /dev/random failure by making sure that it ↵Mounir IDRASSI2-1/+21
has returned random bytes successfully at least once during the lifetime of RandomNumberGenerator
2020-06-19Linux/MacOSX: Complete the change of removal of AES-NI detection function ↵Mounir IDRASSI1-1/+1
done for Windows previously
2020-06-19Windows: Fix wrong results in benchmark of encryption algorithms when RAM ↵Mounir IDRASSI1-0/+5
encryption is enabled
2020-06-19Windows: remove duplicated function to detect AES-NI support in CPUMounir IDRASSI4-24/+4
2020-06-12Windows: Update IDRIX SHA-1 code signing certificate to latest one.Mounir IDRASSI6-39/+39
2020-06-12Translations: fix typo in VeraCrypt name.Mounir IDRASSI2-2/+2
2020-06-12Update donation page with new Euro bank account detailsMounir IDRASSI2-4/+4
2020-06-11Switch from auto_ptr to unique_ptr (#638)Christopher Bergqvist29-73/+71
2020-06-11Update Language.pl.xml (#625)Michal1-3/+3
* Update Language.pl.xml Fixed HPA name & donate now * Update Language.pl.xml Fixed word: timeout
2020-06-11Add .gitignore file for easier change tracking (#604)alt3r 3go1-0/+18
Closes #87. Signed-off-by: alt3r 3go <alt3r.3go@protonmail.com>
2020-06-11Fix indentation in README.md (#596)Ben Mares1-5/+5
The commands in the instructions for Linux and Mac OS X were not displaying in typewriter font.
2020-06-11Updated Dutch translations (based on Transifex project) (#587)Thomas De Rocker1-1194/+1202
Completely reworked Dutch translations (in accordance to the Microsoft style guide, as much as possible). Translated using the dedicated Transifex project by Localization Lab. (https://www.transifex.com/otf/veracrypt/dashboard/) If needed, a Winmerge report (for visual comparison) can be generated. Regards, Thomas De Rocker (RockyTDR)
2020-06-11[Done] Update korean translate (#584)키에르1-11/+11
* Update Language.ko.xml * Update Language.ko.xml
2020-03-11Windows: Update signed Windows driver to version 1.24.15VeraCrypt_1.24-Update6Mounir IDRASSI6-3/+3
008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. Modifications and additions to the original source code (contained in this file) and all other portions of this file are Copyright (c) 2013-2017 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ #include "Language.h" #include "Dlgcode.h" #include "Dictionary.h" #include "Tcdefs.h" #include "Xml.h" #include "../Common/Resource.h" #ifdef TCMOUNT #include "../Mount/Resource.h" #endif #ifdef VOLFORMAT #include "../Format/Resource.h" #endif #ifdef SETUP #include "../Setup/Resource.h" #endif #include <Strsafe.h> BOOL LocalizationActive; int LocalizationSerialNo; wchar_t UnknownString[1024] = {0}; static char *LanguageFileBuffer = NULL; static HANDLE LanguageFileFindHandle = INVALID_HANDLE_VALUE; static char PreferredLangId[6] = {0}; static char *LanguageResource = NULL; 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 () { if (LanguageFileFindHandle != INVALID_HANDLE_VALUE) { FindClose (LanguageFileFindHandle); LanguageFileFindHandle = INVALID_HANDLE_VALUE; } if (LanguageFileBuffer != NULL) { free (LanguageFileBuffer); LanguageFileBuffer = NULL; } LanguageResourceId = 0; if (LanguageResource == NULL) { DWORD size; LanguageResource = MapResource (L"Xml", IDR_LANGUAGE, &size); if (LanguageResource) LanguageResourceSize = size; } if (LanguageResource) { LanguageFileBuffer = malloc(LanguageResourceSize + 1); if (LanguageFileBuffer) { memcpy (LanguageFileBuffer, LanguageResource, LanguageResourceSize); LanguageFileBuffer[LanguageResourceSize] = 0; } } return LanguageFileBuffer; } static char *MapNextLanguageFile (int resourceid) { wchar_t f[TC_MAX_PATH*2], *t; WIN32_FIND_DATAW find; HANDLE file; DWORD read; BOOL bStatus; /* free memory here to avoid leaks */ if (LanguageFileBuffer != NULL) { free (LanguageFileBuffer); LanguageFileBuffer = NULL; } if (resourceid == 0) { 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"); 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; 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; } 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; } 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; if (LanguageResource) { LanguageFileBuffer = malloc(LanguageResourceSize + 1); if (LanguageFileBuffer) { memcpy (LanguageFileBuffer, LanguageResource, LanguageResourceSize); LanguageFileBuffer[LanguageResourceSize] = 0; } } } return LanguageFileBuffer; } static BOOL LoadLanguageData (int resourceid, BOOL bForceSetPreferredLanguage, BOOL bForceSilent) { DWORD size; BYTE *res; char *xml, *header, *headerPtr; char langId[6] = "en", attr[32768], key[128]; BOOL defaultLangParsed = FALSE, langFound = FALSE; WCHAR wattr[32768]; int i, intKey, len; char *xmlElements[] = {"entry", 0}; #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 LocalizationActive = FALSE; ActiveLangPackVersion[0] = 0; ClearDictionaryPool (); LanguageResource = NULL; 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 (resourceid)) { xml = (char *) res; xml = XmlFindElement (xml, "localization"); if (!xml) continue; // Required TrueCrypt version XmlGetAttributeText (xml, "prog-version", attr, sizeof (attr)); // Check version of external language file if (defaultLangParsed && strcmp (attr, VERSION_STRING VERSION_STRING_SUFFIX) && strcmp (attr, "DEBUG")) { 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); if (!bForceSilent) MessageBoxW (NULL, m, L"VeraCrypt", MB_ICONERROR); continue; } // Search language id in language file if (defaultLangParsed) { while (xml = XmlFindElement (xml, "language")) { XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); 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; } } if (!langFound) continue; } // Create font dictionary xml = (char *) res; while (xml = XmlFindElement (xml, "font")) { XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); if (!defaultLangParsed || 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++; } // Create string and control dictionaries for (i = 0; xmlElements[i] != 0; i++) { xml = (char *) res; while (xml = XmlFindElement (xml, xmlElements[i])) { void *key; void *text; XmlGetAttributeText (xml, "lang", attr, sizeof (attr)); if (!defaultLangParsed || 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++; } } if (langFound) break; if (!defaultLangParsed) { defaultLangParsed = TRUE; if ((resourceid == 0) && (langId[0] == 0 || strcmp (langId, "en") == 0)) break; } } LocalizationActive = langFound && strcmp (langId, "en") != 0; LocalizationSerialNo++; if (bForceSetPreferredLanguage) 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; } BOOL LoadLanguageFile () { 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) { WORD lw = LOWORD (wParam); WORD hw = HIWORD (wParam); switch (msg) { case WM_INITDIALOG: { char *xml; char attr[2048], lastLangId[10]; WCHAR wattr[2048]; int len; int langCount = 0; BOOL defaultLangFound = FALSE; LocalizeDialog (hwndDlg, "IDD_LANGUAGE"); ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS); for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile (0)) { while (xml = XmlFindElement (xml, "language")) { XmlGetAttributeText (xml, "name", attr, sizeof (attr)); len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0])); if (len != 0 && (!defaultLangFound || wcscmp (wattr, L"English") != 0)) { int i = (int) SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr); if (i >= 0) { int id; // Encode language id in LPARAM XmlGetAttributeText (xml, "langid", attr, sizeof (attr)); switch (strlen (attr)) { case 2: id = attr[0] | attr[1] << 8; break; case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break; default: continue; } if (!defaultLangFound) defaultLangFound = TRUE; SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id); if (strcmp (attr, PreferredLangId) == 0) { char credits [10000]; WCHAR wcredits [10000]; WCHAR wversion [20]; wchar_t szVers [200]; int nLen; SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0); // Language pack version if (!ActiveLangPackVersion[0] || memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0) { StringCbPrintfW (szVers, sizeof(szVers), GetString("LANG_PACK_VERSION"), L"--"); } else { nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (wversion) / sizeof(wversion[0])); if (nLen != 0) StringCbPrintfW (szVers, sizeof(szVers),GetString("LANG_PACK_VERSION"), wversion); } SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers); // Translator credits XmlGetAttributeText (xml, "translators", credits, sizeof (credits)); nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits) / sizeof(wcredits[0])); if (nLen != 0) { SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits); } } StringCbCopyA (lastLangId, sizeof(lastLangId),attr); langCount++; } } xml++; } } if (lParam == 1) { // Auto mode if (langCount < 2) EndDialog (hwndDlg, IDCANCEL); if (langCount == 2) StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), lastLangId); EndDialog (hwndDlg, IDOK); } return 1; } case WM_COMMAND: if (lw == IDOK || hw == LBN_DBLCLK) { int i = (int) SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0); if (i >= 0) { int id = (int) SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0); if (id != LB_ERR) { char l[6]; // Decode language id from LPARAM l[0] = (char) id; l[1] = (char) (id >> 8); l[2] = 0; if ((id & 0xffff0000) != 0) { l[2] = '-'; l[3] = (char) (id >> 16); l[4] = id >> 24; l[5] = 0; } if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1) StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), l); } } EndDialog (hwndDlg, IDOK); return 1; } if (lw == IDCANCEL) { EndDialog (hwndDlg, lw); return 1; } if (lw == IDC_GET_LANG_PACKS) { char tmpstr [256]; if (strlen (ActiveLangPackVersion) > 0 && strlen (GetPreferredLangId()) > 0) StringCbPrintfA (tmpstr, sizeof(tmpstr), "&langpackversion=%s&lang=%s", ActiveLangPackVersion, GetPreferredLangId()); else tmpstr[0] = 0; Applink ("localizations"); return 1; } return 0; } return 0; } char *GetPreferredLangId () { return PreferredLangId; } void SetPreferredLangId (char *langId) { StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), langId); } char *GetActiveLangPackVersion () { return ActiveLangPackVersion; } wchar_t *GetString (const char *stringId) { WCHAR *str = (WCHAR *) GetDictionaryValue (stringId); if (str != NULL) return str; StringCbPrintfW (UnknownString, sizeof(UnknownString), UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId); return UnknownString; } Font *GetFont (char *fontType) { return (Font *) GetDictionaryValue (fontType); }