Added VIFileVersion instruction and fixed version info resource default language

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6160 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2011-07-29 22:11:00 +00:00
parent 737a5c8468
commit 3cd6ebbf39
7 changed files with 96 additions and 29 deletions

View file

@ -187,7 +187,7 @@ CEXEBuild::CEXEBuild() :
// Added by ramon 6 jun 2003
#ifdef NSIS_SUPPORT_VERSION_INFO
version_product_v[0]=0;
version_fixedflags=0;
#endif
build_overwrite=build_last_overwrite=0;
@ -1744,23 +1744,23 @@ int CEXEBuild::AddVersionInfo()
{
GrowBuf VerInfoStream;
// Should probably check for (4 & version_fixedflags) here, but VIProductVersion without VIAddVersionKey
// fails silently, so VIFileVersion does the same...
if ( rVersionInfo.GetStringTablesCount() > 0 )
{
if ( !version_product_v[0] )
if ( !(1 & version_fixedflags) )
{
ERROR_MSG(_T("Error: VIProductVersion is required when other version information functions are used.\n"));
return PS_ERROR;
}
else
{
int imm, iml, ilm, ill;
if ( _stscanf(version_product_v, _T("%d.%d.%d.%d"), &imm, &iml, &ilm, &ill) != 4 )
if ( !(2 & version_fixedflags) )
{
ERROR_MSG(_T("Error: invalid VIProductVersion format, should be X.X.X.X\n"));
// This error string should match the one used by the TOK_VI_SETFILEVERSION handler
ERROR_MSG(_T("Error: invalid %s format, should be X.X.X.X\n"),_T("VIProductVersion"));
return PS_ERROR;
}
rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
rVersionInfo.SetProductVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
try
{
@ -1770,14 +1770,19 @@ int CEXEBuild::AddVersionInfo()
LANGID lang_id = rVersionInfo.GetLangID(i);
int code_page = rVersionInfo.GetCodePage(i);
const TCHAR *lang_name = GetLangNameAndCP(lang_id);
const TCHAR *lang_name = GetLangNameAndCPForVersionResource(lang_id, NULL, false);
if ( !rVersionInfo.FindKey(lang_id, code_page, _T("FileVersion")) )
warning(_T("Generating version information for language \"%04d-%s\" without standard key \"FileVersion\""), lang_id, lang_name);
if ( !rVersionInfo.FindKey(lang_id, code_page, _T("FileDescription")) )
warning(_T("Generating version information for language \"%04d-%s\" without standard key \"FileDescription\""), lang_id, lang_name);
if ( !rVersionInfo.FindKey(lang_id, code_page, _T("LegalCopyright")) )
warning(_T("Generating version information for language \"%04d-%s\" without standard key \"LegalCopyright\""), lang_id, lang_name);
const TCHAR *recverkeys =
_T("FileVersion\0")
_T("FileDescription\0")
_T("LegalCopyright\0");
for(;;)
{
if ( !*recverkeys ) break;
if ( !rVersionInfo.FindKey(lang_id, code_page, recverkeys) )
warning(_T("Generating version information for language \"%04d-%s\" without standard key \"%s\""), lang_id, lang_name, recverkeys);
recverkeys += _tcsclen(recverkeys) + 1;
}
rVersionInfo.ExportToStream(VerInfoStream, i);
res_editor->UpdateResource(RT_VERSION, 1, lang_id, (BYTE*)VerInfoStream.get(), VerInfoStream.getlen());

View file

@ -301,8 +301,9 @@ class CEXEBuild {
* out parameter. It will look for a LanguageTable to get the values.
* If not found, then it will set the codepage to English for ANSI
* or Unicode for Unicode version of NSIS. The language name is looked
* up via the LanguageTable if it exists, otherwise, it calls
* GetLocaleInfo() with the LANGID to get the string.
* up via the LanguageTable if it exists, otherwise, it returns "???" except
* a hardcoded check for 1033 (english). It really should fall back to
* calling GetLocaleInfo() with the LANGID to get the string.
*
* This function is not thread-safe! For a thread-safe version, the
* parameter must include the buffer to write to.
@ -312,6 +313,7 @@ class CEXEBuild {
* @return The language string in English.
*/
const TCHAR *GetLangNameAndCP(LANGID lang, unsigned int *codepage = NULL);
const TCHAR *GetLangNameAndCPForVersionResource(LANGID &lang, unsigned int *codepage = NULL, bool deflangfallback = true);
int DefineLangString(const TCHAR *name, int process=-1);
int DefineInnerLangString(int id, int process=-1);
@ -426,7 +428,7 @@ class CEXEBuild {
// Added by ramon 6 jun 2003
#ifdef NSIS_SUPPORT_VERSION_INFO
CResourceVersionInfo rVersionInfo;
TCHAR version_product_v[1024];
unsigned int version_fixedflags;
#endif
int sectiongroup_open_cnt;

View file

@ -381,8 +381,8 @@ const TCHAR *CEXEBuild::GetLangNameAndCP(LANGID lang, unsigned int *codepage/*=N
return table->nlf.m_szName;
}
else {
// If the language table does not exist, then we default to Unicode or ANSI
// depending on the target installer type
// If the language table does not exist, then we default to Unicode or ANSI
// depending on the target installer type
if (codepage)
*codepage = build_unicode ? 1200 : 1252; // Unicode or CP1252
@ -393,6 +393,17 @@ const TCHAR *CEXEBuild::GetLangNameAndCP(LANGID lang, unsigned int *codepage/*=N
}
}
const TCHAR *CEXEBuild::GetLangNameAndCPForVersionResource(LANGID &lang, unsigned int *codepage/*=NULL*/, bool deflangfallback/*=true*/) {
const TCHAR *langname = GetLangNameAndCP(lang, codepage);
if (0 == lang) {
if (deflangfallback)
lang = last_used_lang;
else
langname = _T("Neutral");
}
return langname;
}
int CEXEBuild::DefineLangString(const TCHAR *name, int process/*=-1*/) {
int index, uindex, pos, ret, sn;

View file

@ -5912,6 +5912,9 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
{
LANGID LangID=0;
int a = 1;
// Allow people to force Neutral, if /LANG=* is not present it uses the default
const bool forceneutrallang = !_tcsicmp(line.gettoken_str(a),_T("/LANG=0"));
if (!_tcsnicmp(line.gettoken_str(a),_T("/LANG="),6))
LangID=_ttoi(line.gettoken_str(a++)+6);
if (line.getnumtokens()!=a+2) PRINTHELP();
@ -5925,12 +5928,16 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
else
{
SCRIPT_MSG(_T("%s: \"%s\" \"%s\"\n"), line.gettoken_str(0), line.gettoken_str(a), line.gettoken_str(a+1));
LANGID lReaded = LangID;
if ( a > 1 && lReaded == 0 )
warning_fl(_T("%s: %s language not loaded, using default \"1033-English\""), line.gettoken_str(0), line.gettoken_str(1));
const bool allowdeflangfallback = a <= 1 && !forceneutrallang;
if ( a > 1 && 0 == LangID && !forceneutrallang)
{
ERROR_MSG(_T("%s: \"%s\" is not a valid language code!\n"),line.gettoken_str(0), line.gettoken_str(1));
return PS_ERROR;
}
unsigned int codepage;
const TCHAR *lang_name = GetLangNameAndCP(LangID, &codepage);
// We rely on GetLangNameAndCPForVersionResource to update LangID if required
const TCHAR *lang_name = GetLangNameAndCPForVersionResource(LangID, &codepage, allowdeflangfallback);
if ( rVersionInfo.SetKeyValue(LangID, codepage, pKey, pValue) )
{
@ -5941,18 +5948,49 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
return PS_OK;
}
}
case TOK_VI_SETPRODUCTVERSION:
if ( version_product_v[0] )
case TOK_VI_SETPRODUCTVERSION:
case TOK_VI_SETFILEVERSION:
// Probably not required, but this code retains the <= 2.46 behaviour and
// does not fail on bad product version number here, it "validates" in CEXEBuild::AddVersionInfo()
//
// It is ok for us to use rVersionInfo as storage since VIProductVersion is required by VIAddVersionKey
{
ERROR_MSG(_T("Error: %s already defined!\n"), line.gettoken_str(0));
return PS_ERROR;
const bool settingFileVer = TOK_VI_SETFILEVERSION == which_token;
const unsigned int reuseFlag = settingFileVer ? 4 : 1;
if (reuseFlag & version_fixedflags)
{
ERROR_MSG(_T("Error: %s already defined!\n"), line.gettoken_str(0));
return PS_ERROR;
}
version_fixedflags |= reuseFlag;
int imm, iml, ilm, ill;
const bool validInput = _stscanf(line.gettoken_str(1), _T("%d.%d.%d.%d"), &imm, &iml, &ilm, &ill) == 4;
if (settingFileVer)
{
if (!validInput)
{
ERROR_MSG(_T("Error: invalid %s format, should be X.X.X.X\n"),line.gettoken_str(0));
return PS_ERROR;
}
rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
}
else
{
if (validInput)
{
version_fixedflags |= 2;
rVersionInfo.SetProductVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
// FileVersion defaults to ProductVersion
if (!(4 & version_fixedflags)) rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
}
}
}
_tcscpy(version_product_v, line.gettoken_str(1));
return PS_OK;
#else
case TOK_VI_ADDKEY:
case TOK_VI_SETPRODUCTVERSION:
case TOK_VI_SETFILEVERSION:
ERROR_MSG(_T("Error: %s specified, NSIS_SUPPORT_VERSION_INFO not defined.\n"),line.gettoken_str(0));
return PS_ERROR;
#endif

View file

@ -292,6 +292,7 @@ static tokenType tokenlist[TOK__LAST] =
// Added by ramon 6 jun 2003
{TOK_VI_ADDKEY,_T("VIAddVersionKey"),2,1,_T("/LANG=lang_id keyname value"),TP_GLOBAL},
{TOK_VI_SETPRODUCTVERSION,_T("VIProductVersion"),1,0,_T("[version_string_X.X.X.X]"),TP_GLOBAL},
{TOK_VI_SETFILEVERSION,_T("VIFileVersion"),1,0,_T("[version_string_X.X.X.X]"),TP_GLOBAL},
{TOK_LOCKWINDOW,_T("LockWindow"),1,0,_T("(on|off)"),TP_CODE},
};

View file

@ -70,6 +70,7 @@ enum
TOK_DEFVAR,
TOK_VI_ADDKEY,
TOK_VI_SETPRODUCTVERSION,
TOK_VI_SETFILEVERSION,
#ifdef _UNICODE
TOK_TARGETMINIMALOS,
#endif