Version Information now rely on languages, some more updates on named uservars, maybe last one before official release :) (preview UserVars.nsi - doesn't compile yet)

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2633 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
ramon18 2003-06-12 00:06:23 +00:00
parent 7adbddc567
commit 1ea2160310
14 changed files with 539 additions and 283 deletions

46
Examples/UserVars.nsi Normal file
View file

@ -0,0 +1,46 @@
; VersionInfo.nsi
;
; This script shows you how to declare and user VARIABLES.
;--------------------------------
!include "MUI.nsh"
!define MUI_PRODUCT "User Variables"
!define MUI_VERSION "1.0"
;--------------------------------
;Configuration
;General
OutFile "UserVars.exe"
ShowInstDetails nevershow
;--------------------------------
;Pages
!insertmacro MUI_PAGE_INSTFILES
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
; Declaration of User Variables with command DIM, allowed charaters for variables names : [a-z][A-Z][0-9] and '_'
DIM "Name"
DIM "Serial"
;--------------------------------
;Installer Sections
Section "Dummy Section" SecCopyUI
StrCpy $0 "Admin"
StrCpy "$Name" $0
StrCpy "$Serial" "12345"
MessageBox MB_OK "User Name: $Name$\n$\nSerial Number: $Serial"
SectionEnd

View file

@ -12,19 +12,17 @@ OutFile "VersionInfo.exe"
;--------------------------------
;Version Information
VISetVersionLanguage 2057 1200 ; English UK
VIAddTranslation 2057 1200 ; English UK
VIProductVersion "1.2.3.4"
VIAddVersionKey "ProductName" "Test Application"
VIAddVersionKey "Comments" "A test comment"
VIAddVersionKey "CompanyName" "Fake company"
VIAddVersionKey "LegalTrademarks" "Test Application is a trademark of Fake company"
VIAddVersionKey "LegalCopyright" "© Fake company"
VIAddVersionKey "FileDescription" "Test Application"
VIAddVersionKey "FileVersion" "1.2.3"
VIAddVersionKey ${LANG_ENGLISH} "ProductName" "Test Application"
VIAddVersionKey ${LANG_ENGLISH} "Comments" "A test comment"
VIAddVersionKey ${LANG_ENGLISH} "CompanyName" "Fake company"
VIAddVersionKey ${LANG_ENGLISH} "LegalTrademarks" "Test Application is a trademark of Fake company"
VIAddVersionKey ${LANG_ENGLISH} "LegalCopyright" "© Fake company"
VIAddVersionKey ${LANG_ENGLISH} "FileDescription" "Test Application"
VIAddVersionKey ${LANG_ENGLISH} "FileVersion" "1.2.3"
;--------------------------------
Section ""
SectionEnd
SectionEnd

View file

@ -28,12 +28,24 @@ CResourceVersionInfo::CResourceVersionInfo()
// Detect local codepage and language
WORD Lang = GetSystemDefaultLangID();
WORD CodePage = GetACP();
char Buff[10];
sprintf(Buff, "%04x%04x", Lang, CodePage);
SetVersionInfoLang(Buff);
/*
SetKeyValue(Lang, CodePage, "Comments", "Portuguese");
SetKeyValue(Lang, CodePage, "FileVersion", "1.2");
SetKeyValue(Lang, CodePage, "FileDescription", "Soft");
SetKeyValue(Lang, CodePage, "LegalCopyright", "My");
SetKeyValue(Lang, CodePage, "InternalName", "My");
SetKeyValue(Lang, CodePage, "CompanyName", "rats");
SetKeyValue(Lang, CodePage, "ProductVersion", "ProductVersion");
AddTranslation(CodePage, Lang);
b_CustomTranslations = false;
Lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
SetKeyValue(Lang, CodePage, "Comments", "English");
SetKeyValue(Lang, CodePage, "FileVersion", "1.2");
SetKeyValue(Lang, CodePage, "FileDescription", "Soft");
SetKeyValue(Lang, CodePage, "LegalCopyright", "My");
SetKeyValue(Lang, CodePage, "InternalName", "My");
SetKeyValue(Lang, CodePage, "CompanyName", "rats");
SetKeyValue(Lang, CodePage, "ProductVersion", "ProductVersion");
*/
}
CResourceVersionInfo::~CResourceVersionInfo()
@ -58,14 +70,13 @@ void CResourceVersionInfo::SetProductVersion(int HighPart, int LowPart)
m_FixedInfo.dwProductVersionMS = HighPart;
}
// Util function
wstring StrToWstr(const string& istr)
// Util function - must be freeded
WCHAR* StrToWstrAlloc(const char* istr, int codepage)
{
wstring wstr;
for(string::const_iterator it = istr.begin(); it != istr.end(); ++it)
{
wstr += (unsigned char)*it;
} return wstr;
int strSize = strlen(istr);
WCHAR* wstr = new WCHAR[(strSize*2)];
MultiByteToWideChar(codepage, 0, istr, -1, wstr, strSize*2);
return wstr;
}
int GetVersionHeader (LPSTR &p, WORD &wLength, WORD &wValueLength, WORD &wType)
@ -95,7 +106,7 @@ void PadStream (GrowBuf &strm)
strm.add (&ZEROS, 4 - (strm.getlen() % 4));
}
void SaveVersionHeader (GrowBuf &strm, WORD wLength, WORD wValueLength, WORD wType, const wstring &key, void *value)
void SaveVersionHeader (GrowBuf &strm, WORD wLength, WORD wValueLength, WORD wType, const WCHAR *key, void *value)
{
WORD valueLen;
WORD keyLen;
@ -104,8 +115,8 @@ void SaveVersionHeader (GrowBuf &strm, WORD wLength, WORD wValueLength, WORD wTy
strm.add (&wValueLength, sizeof (wValueLength));
strm.add (&wType, sizeof (wType));
keyLen = (key.length() + 1) * sizeof (WCHAR);
strm.add ((void*)key.c_str(), keyLen);
keyLen = (wcslen(key) + 1) * sizeof (WCHAR);
strm.add ((void*)key, keyLen);
PadStream(strm);
@ -118,112 +129,129 @@ void SaveVersionHeader (GrowBuf &strm, WORD wLength, WORD wValueLength, WORD wTy
}
}
void CResourceVersionInfo::ExportToStream(GrowBuf &strm)
void CResourceVersionInfo::ExportToStream(GrowBuf &strm, int Index)
{
DWORD v;
WORD wSize;
int p, p1;
wstring KeyName, KeyValue;
WCHAR *KeyName, *KeyValue;
strm.resize(0);
SaveVersionHeader (strm, 0, sizeof (VS_FIXEDFILEINFO), 0, L"VS_VERSION_INFO", &m_FixedInfo);
if ( m_ChildStrings.getnum() > 0 )
DefineList *pChildStrings = m_ChildStringLists.get_strings(Index);
if ( pChildStrings->getnum() > 0 )
{
GrowBuf stringInfoStream;
KeyName = StrToWstr(m_VersionInfoLang);
GrowBuf stringInfoStream;
int codepage = m_ChildStringLists.get_codepage(Index);
LANGID langid = m_ChildStringLists.get_lang(Index);
char Buff[16];
sprintf(Buff, "%04x%04x", langid, codepage);
KeyName = StrToWstrAlloc(Buff, CP_ACP);
SaveVersionHeader (stringInfoStream, 0, 0, 0, KeyName, &ZEROS);
delete [] KeyName;
for ( int i = 0; i < pChildStrings->getnum(); i++ )
{
PadStream (stringInfoStream);
SaveVersionHeader (stringInfoStream, 0, 0, 0, KeyName.c_str(), &ZEROS);
p = stringInfoStream.getlen();
KeyName = StrToWstrAlloc(pChildStrings->getname(i), codepage);
KeyValue = StrToWstrAlloc(pChildStrings->getvalue(i), codepage);
SaveVersionHeader (stringInfoStream, 0, wcslen(KeyValue) + 1, 1, KeyName, (void*)KeyValue);
delete [] KeyName;
delete [] KeyValue;
wSize = stringInfoStream.getlen() - p;
for ( int i = 0; i < m_ChildStrings.getnum(); i++ )
{
PadStream (stringInfoStream);
p = stringInfoStream.getlen();
KeyName = StrToWstr(m_ChildStrings.getname(i));
KeyValue = StrToWstr(m_ChildStrings.getvalue(i));
SaveVersionHeader (stringInfoStream, 0, KeyValue.length() + 1, 1, KeyName.c_str(), (void*)KeyValue.c_str());
wSize = stringInfoStream.getlen() - p;
*(WORD*)((PBYTE)stringInfoStream.get()+p)=wSize;
}
wSize = stringInfoStream.getlen();
*(WORD*)((PBYTE)stringInfoStream.get())=wSize;
PadStream (strm);
p = strm.getlen();
SaveVersionHeader (strm, 0, 0, 0, L"StringFileInfo", &ZEROS);
strm.add (stringInfoStream.get(), stringInfoStream.getlen());
wSize = strm.getlen() - p;
*(WORD*)((PBYTE)strm.get()+p)=wSize;
*(WORD*)((PBYTE)stringInfoStream.get()+p)=wSize;
}
wSize = stringInfoStream.getlen();
*(WORD*)((PBYTE)stringInfoStream.get())=wSize;
PadStream (strm);
p = strm.getlen();
SaveVersionHeader (strm, 0, 0, 0, L"StringFileInfo", &ZEROS);
strm.add (stringInfoStream.get(), stringInfoStream.getlen());
wSize = strm.getlen() - p;
*(WORD*)((PBYTE)strm.get()+p)=wSize;
}
if ( m_Translations.size() > 0 )
// Show all languages avaiable using Var-Translations
if ( m_ChildStringLists.getnum() > 0 )
{
PadStream (strm);
p = strm.getlen();
SaveVersionHeader (strm, 0, 0, 0, L"VarFileInfo", &ZEROS);
PadStream (strm);
p1 = strm.getlen();
SaveVersionHeader (strm, 0, 0, 0, L"Translation", &ZEROS);
for ( int i = 0; i < m_Translations.size(); i++ )
PadStream (strm);
p = strm.getlen();
SaveVersionHeader (strm, 0, 0, 0, L"VarFileInfo", &ZEROS);
PadStream (strm);
p1 = strm.getlen();
SaveVersionHeader (strm, 0, 0, 0, L"Translation", &ZEROS);
// First add selected code language translation
v = MAKELONG(m_ChildStringLists.get_lang(Index), m_ChildStringLists.get_codepage(Index));
strm.add (&v, sizeof (v));
for ( int k =0; k < m_ChildStringLists.getnum(); k++ )
{
if ( k != Index )
{
v = m_Translations[i];
strm.add (&v, sizeof (v));
v = MAKELONG(m_ChildStringLists.get_lang(k), m_ChildStringLists.get_codepage(k));
strm.add (&v, sizeof (v));
}
wSize = strm.getlen() - p1;
*(WORD*)((PBYTE)strm.get()+p1)=wSize;
wSize = sizeof (int) * m_Translations.size();
p1+=sizeof(WORD);
*(WORD*)((PBYTE)strm.get()+p1)=wSize;
wSize = strm.getlen() - p;
*(WORD*)((PBYTE)strm.get()+p)=wSize;
}
wSize = strm.getlen() - p1;
*(WORD*)((PBYTE)strm.get()+p1)=wSize;
wSize = sizeof (int) * m_ChildStringLists.getnum();
p1+=sizeof(WORD);
*(WORD*)((PBYTE)strm.get()+p1)=wSize;
wSize = strm.getlen() - p;
*(WORD*)((PBYTE)strm.get()+p)=wSize;
}
wSize = strm.getlen();
*(WORD*)((PBYTE)strm.get())=wSize;
}
void CResourceVersionInfo::SetKeyValue(char* AKeyName, char* AValue)
// Returns 0 if success, 1 if already defined
int CResourceVersionInfo::SetKeyValue(LANGID lang_id, int codepage, char* AKeyName, char* AValue)
{
m_ChildStrings.add(AKeyName, AValue);
int pos = m_ChildStringLists.find(lang_id, codepage);
if ( pos == -1 )
{
pos = m_ChildStringLists.add(lang_id, codepage);
}
DefineList *pStrings = m_ChildStringLists.get_strings(pos);
return pStrings->add(AKeyName, AValue);
}
void CResourceVersionInfo::AddTranslation(WORD CodePage, WORD LangID )
int CResourceVersionInfo::GetStringTablesCount()
{
if ( !b_CustomTranslations )
{
b_CustomTranslations = true;
m_Translations.clear(); // remove local system default, user want to customize
}
DWORD dwTrans = MAKELONG(LangID, CodePage);
if ( find(m_Translations.begin(), m_Translations.end(), dwTrans) == m_Translations.end() )
m_Translations.push_back(dwTrans);
return m_ChildStringLists.getnum();
}
int CResourceVersionInfo::GetKeyCount()
LANGID CResourceVersionInfo::GetLangID(int Index)
{
return m_ChildStrings.getnum();
return m_ChildStringLists.get_lang(Index);
}
int CResourceVersionInfo::GetTranslationCount()
int CResourceVersionInfo::GetCodePage(int Index)
{
return m_Translations.size();
return m_ChildStringLists.get_codepage(Index);
}
char *CResourceVersionInfo::FindKey(char *pKeyName)
char *CResourceVersionInfo::FindKey(LANGID LangID, int codepage, char *pKeyName)
{
return m_ChildStrings.find(pKeyName);
}
void CResourceVersionInfo::SetVersionInfoLang(char *pLandCp)
{
m_VersionInfoLang = pLandCp;
int pos = m_ChildStringLists.find(LangID, codepage);
if ( pos == -1 )
{
return NULL;
}
DefineList *pStrings = m_ChildStringLists.get_strings(pos);
return pStrings->find(pKeyName);
}
bool CResourceVersionInfo::IsValidCodePage(WORD codePage )

View file

@ -14,28 +14,83 @@
#include <algorithm>
using namespace std;
struct version_string_list {
int codepage;
LANGID lang_id;
int name;
DefineList *pChildStrings;
};
class CVersionStrigList : public SortedStringListND<struct version_string_list>
{
public:
int add(LANGID langid, int codepage)
{
char Buff[10];
sprintf(Buff, "%04x", langid);
int pos = SortedStringListND<struct version_string_list>::add(Buff);
if (pos == -1) return false;
((struct version_string_list*)gr.get())[pos].pChildStrings = new DefineList;
((struct version_string_list*)gr.get())[pos].codepage = codepage;
((struct version_string_list*)gr.get())[pos].lang_id = langid;
return pos;
}
LANGID get_lang(int idx)
{
version_string_list *data=(version_string_list *)gr.get();
return data[idx].lang_id;
}
int get_codepage(int idx)
{
version_string_list *data=(version_string_list *)gr.get();
return data[idx].codepage;
}
DefineList* get_strings(int idx)
{
version_string_list *data=(version_string_list *)gr.get();
return data[idx].pChildStrings;
}
int find(LANGID lang_id, int codepage)
{
char Buff[10];
sprintf(Buff, "%04x", lang_id);
return SortedStringListND<struct version_string_list>::find(Buff);
}
int getlen()
{
return strings.getlen();
}
int getnum()
{
return gr.getlen()/sizeof(struct version_string_list);
}
};
/////////////////////////////////////////////////////////////////////////////////////////////
class CResourceVersionInfo
{
VS_FIXEDFILEINFO m_FixedInfo;
DefineList m_ChildStrings;
vector< DWORD > m_Translations;
string m_VersionInfoLang;
bool b_CustomTranslations;
CVersionStrigList m_ChildStringLists;
char m_VersionInfoLang[10];
public:
CResourceVersionInfo();
virtual ~CResourceVersionInfo();
void SetKeyValue (char *AKeyName, char *AValue);
void AddTranslation(WORD CodePage, WORD LangID );
int SetKeyValue(LANGID lang_id, int codepage, char* AKeyName, char* AValue);
void SetFileFlags(int Value);
void SetFileVersion(int HighPart, int LowPart);
void SetProductVersion(int HighPart, int LowPart);
void ExportToStream(GrowBuf &strm);
int GetKeyCount();
int GetTranslationCount();
char *FindKey(char *pKeyName);
void SetVersionInfoLang(char *pLandCp);
void ExportToStream(GrowBuf &strm, int Index);
int GetStringTablesCount();
LANGID GetLangID(int Index);
int GetCodePage(int Index);
char *FindKey(LANGID LangID, int codepage, char *pKeyName);
bool IsValidCodePage(WORD codePage );
};

View file

@ -13,6 +13,11 @@
#include "exehead/lang.h"
#include "ResourceVersionInfo.h"
bool isSimpleChar(char ch)
{
return (ch == '_' ) || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}
void CEXEBuild::define(const char *p, const char *v)
{
definedlist.add(p,v);
@ -241,8 +246,6 @@ CEXEBuild::CEXEBuild()
// Added by ramon 6 jun 2003
#ifdef NSIS_SUPPORT_VERSION_INFO
version_codePage=0;
version_lang=0;
version_product_v[0]=0;
#endif
@ -305,6 +308,9 @@ CEXEBuild::CEXEBuild()
#endif
last_used_lang=MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
char lang_id[16];
wsprintf(lang_id, "%u", last_used_lang);
definedlist.add("LANG_ENGLISH",lang_id);
build_header.common.num_pages=0;
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
@ -335,6 +341,37 @@ CEXEBuild::CEXEBuild()
use_first_insttype=true;
build_header.license_bg=-COLOR_BTNFACE;
#ifdef NSIS_SUPPORT_NAMED_USERVARS
// Register user variables $0, $1 and so one
char Aux[3];
for ( int i = 0; i < 10; i++ ) // 0 - 9
{
sprintf(Aux, "%d", i);
DeclaredUserVar(Aux);
}
for ( i = 0; i < 10; i++ ) // 10 - 19
{
sprintf(Aux, "R%d", i);
DeclaredUserVar(Aux);
}
DeclaredUserVar("CMDLINE"); // 20 everything before here doesn't have trailing slash removal
DeclaredUserVar("INSTDIR"); // 21
DeclaredUserVar("OUTDIR"); // 22
DeclaredUserVar("EXEDIR"); // 23
DeclaredUserVar("LANGUAGE"); // 24
DeclaredUserVar("PLUGINSDIR"); // 25
DeclaredUserVar("PROGRAMFILES"); // 26
DeclaredUserVar("SMPROGRAMS"); // 27
DeclaredUserVar("SMSTARTUP"); // 28
DeclaredUserVar("DESKTOP"); // 29
DeclaredUserVar("STARTMENU"); // 30
DeclaredUserVar("QUICKLAUNCH"); // 31
DeclaredUserVar("TEMP"); // 32
DeclaredUserVar("WINDIR"); // 33
DeclaredUserVar("SYSDIR"); // 34 everything after here doesn't have trailing slash removal
DeclaredUserVar("HWNDPARENT"); // 35
#endif
}
int CEXEBuild::getcurdbsize() { return cur_datablock->getlen(); }
@ -355,6 +392,7 @@ int CEXEBuild::add_intstring(const int i) // returns offset in stringblock
// based on Dave Laundon's code
int CEXEBuild::preprocess_string(char *out, const char *in)
{
#ifndef NSIS_SUPPORT_NAMED_USERVARS
static const char VarNames[] =
"HWNDPARENT\0" // 0
"0\0" // 1
@ -394,7 +432,8 @@ int CEXEBuild::preprocess_string(char *out, const char *in)
"WINDIR\0" // 34
"SYSDIR\0" // 35
;
#endif
const char *p=in;
while (*p)
{
@ -406,9 +445,15 @@ int CEXEBuild::preprocess_string(char *out, const char *in)
while (l--)
{
int i = (unsigned char)*p++;
#ifndef NSIS_SUPPORT_NAMED_USERVARS
if (i >= VAR_CODES_START) {
*out++ = (char)255;
}
#else
if (i == VAR_CODES_START || i == 255 ) {
*out++ = (char)255;
}
#endif
*out++=i;
}
continue;
@ -418,16 +463,25 @@ int CEXEBuild::preprocess_string(char *out, const char *in)
p=np;
#ifndef NSIS_SUPPORT_NAMED_USERVARS
// Test for characters extending into the variable codes
if (i >= VAR_CODES_START) {
*out++ = (char)255;
}
#else
// Test for characters that equals to control char of variable codes
if (i == VAR_CODES_START || i == 255 ) {
*out++ = (char)255;
}
#endif
else if (i == '$')
{
if (*p == '$')
p++; // Can simply convert $$ to $ now
else
{
#ifndef NSIS_SUPPORT_NAMED_USERVARS
const char *pVarName;
for (
pVarName = VarNames, i = VAR_CODES_START;
@ -444,43 +498,30 @@ int CEXEBuild::preprocess_string(char *out, const char *in)
p += strlen(pVarName);
}
else // warning should go here
#endif // not NSIS_SUPPORT_NAMED_USERVARS
{
#ifdef NSIS_SUPPORT_NAMED_USERVARS
bool bProceced=false;
if ( *p == '[' )
if ( *p )
{
char *pUserVarName = (char *)p+1;
while ( *pUserVarName )
const char *pUserVarName = p;
while ( isSimpleChar(*pUserVarName) )
pUserVarName++;
while ( pUserVarName > p )
{
if ( *pUserVarName == ']' )
{
*pUserVarName='\0';
int idxUserVar = m_UserVarNames.get((char*)p+1);
int varLen = strlen(p)+1;
*pUserVarName=']'; // restore
const char * Debug = p-(pUserVarName-p);
int idxUserVar = m_UserVarNames.get((char*)p, pUserVarName-p);
if ( idxUserVar >= 0 )
{
*out++=(unsigned int)VAR_CODES_START + 36; // Named user variable;
*(WORD*)out=((WORD)idxUserVar+USER_VARS_COUNT) | 0xF000;
*out++=(unsigned int)VAR_CODES_START; // Named user variable;
*(WORD*)out=((WORD)idxUserVar+1) | 0xF000;
out += sizeof(WORD);
p += varLen;
p += pUserVarName-p;
bProceced = true;
{
for ( WORD i = 0; i < 0x0FFF; i++ )
{
WORD bb = i | 0xF000;
WORD ok = bb & 0x0FFF;
if ( ok != i )
{
warning("Problems with %d",i);
}
}
}
break;
}
break;
}
pUserVarName++;
pUserVarName--;
}
}
if ( bProceced )
@ -1273,7 +1314,7 @@ int CEXEBuild::write_output(void)
GrowBuf VerInfoStream;
bool bNeedVInfo = false;
if ( rVersionInfo.GetKeyCount() > 0 )
if ( rVersionInfo.GetStringTablesCount() > 0 )
{
if ( !version_product_v[0] )
{
@ -1291,19 +1332,23 @@ int CEXEBuild::write_output(void)
rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
rVersionInfo.SetProductVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
//rVersionInfo.AddTranslation(0x0,0x0409);
rVersionInfo.ExportToStream(VerInfoStream);
init_res_editor();
res_editor->UpdateResource(RT_VERSION, 1, 0, (BYTE*)VerInfoStream.get(), VerInfoStream.getlen());
for ( int i = 0; i < rVersionInfo.GetStringTablesCount(); i++ )
{
LANGID lang_id = rVersionInfo.GetLangID(i);
int code_page = rVersionInfo.GetCodePage(i);
StringTable * Table = GetTable(lang_id);
if ( !rVersionInfo.FindKey(lang_id, code_page, "FileVersion") )
warning("Generating version information for language \"%04d-%s\" without standard key \"FileVersion\"", lang_id, Table->nlf ? Table->nlf->m_szName : lang_id == 1033 ? "English" : "???");
if ( !rVersionInfo.FindKey(lang_id, code_page, "FileDescription") )
warning("Generating version information for language \"%04d-%s\" without standard key \"FileDescription\"", lang_id, Table->nlf ? Table->nlf->m_szName : lang_id == 1033 ? "English" : "???");
if ( !rVersionInfo.FindKey(lang_id, code_page, "LegalCopyright") )
warning("Generating version information for language \"%04d-%s\" without standard key \"LegalCopyright\"", lang_id, Table->nlf ? Table->nlf->m_szName : lang_id == 1033 ? "English" : "???");
if ( !rVersionInfo.GetTranslationCount() )
warning("Generating version information without any language/codepage defined.");
if ( !rVersionInfo.FindKey("FileVersion") )
warning("Generating version information without standard key \"FileVersion\"");
if ( !rVersionInfo.FindKey("FileDescription") )
warning("Generating version information without standard key \"FileDescription\"");
if ( !rVersionInfo.FindKey("LegalCopyright") )
warning("Generating version information without standard key \"LegalCopyright\"");
rVersionInfo.ExportToStream(VerInfoStream, i);
res_editor->UpdateResource(RT_VERSION, 1, lang_id, (BYTE*)VerInfoStream.get(), VerInfoStream.getlen());
}
}
}
@ -2419,6 +2464,11 @@ int CEXEBuild::add_plugins_dir_initializer(void)
int ret;
int zero_offset;
#ifdef NSIS_SUPPORT_NAMED_USERVARS
int var_zero;
var_zero=m_UserVarNames.get("0");
#endif
again:
// Function [un.]Initialize_____Plugins
ret=add_function(uninstall?"un.Initialize_____Plugins":"Initialize_____Plugins");
@ -2441,7 +2491,11 @@ again:
ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(exec_error));
if (ret != PS_OK) return ret;
// GetTempFileName $0
#ifdef NSIS_SUPPORT_NAMED_USERVARS
ret=add_entry_direct(EW_GETTEMPFILENAME, var_zero);
#else
ret=add_entry_direct(EW_GETTEMPFILENAME);
#endif
if (ret != PS_OK) return ret;
// Delete $0 - the temp file created
ret=add_entry_direct(EW_DELETEFILE, zero_offset);
@ -2453,10 +2507,18 @@ again:
ret=add_entry_direct(EW_IFFLAG, ns_label.add("Initialize_____Plugins_error",0), 0, FIELD_OFFSET(installer_flags, exec_error)/sizeof(int));
if (ret != PS_OK) return ret;
// Copy $0 to $PLUGINSDIR
#ifdef NSIS_SUPPORT_NAMED_USERVARS
ret=add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get("PLUGINSDIR"), zero_offset);
#else
ret=add_entry_direct(EW_ASSIGNVAR, 25, zero_offset);
#endif
if (ret != PS_OK) return ret;
// Pop $0
#ifdef NSIS_SUPPORT_NAMED_USERVARS
ret=add_entry_direct(EW_PUSHPOP, var_zero, 1);
#else
ret=add_entry_direct(EW_PUSHPOP, 0, 1);
#endif
if (ret != PS_OK) return ret;
// done
@ -2532,12 +2594,9 @@ int CEXEBuild::DeclaredUserVar(const char *szVarName)
{
while ( *pVarName )
{
if ((*pVarName < '0') ||
(*pVarName > '9' && *pVarName < 'A' ) ||
(*pVarName > 'Z' && *pVarName < 'a' && *pVarName != '_' ) ||
(*pVarName > 'z') )
if ( !isSimpleChar(*pVarName) )
{
ERROR_MSG("Error: invalid charaters in variable name \"%s\"\n", szVarName);
ERROR_MSG("Error: invalid charaters in variable name \"%s\", use only charaters [a-z][A-Z][0-9] and '_'\n", szVarName);
return PS_ERROR;
}
pVarName++;
@ -2556,35 +2615,23 @@ int CEXEBuild::DeclaredUserVar(const char *szVarName)
int CEXEBuild::GetUserVarIndex(LineParser &line, int token)
{
#ifdef NSIS_SUPPORT_NAMED_USERVARS
char *p = line.gettoken_str(token);
if ( *p == '$' && *(p+1) )
{
int idxUserVar = m_UserVarNames.get((char *)p+1);
if ( idxUserVar >= 0 )
{
return idxUserVar;
}
}
return -1;
#else
static const char *usrvars="$0\0$1\0$2\0$3\0$4\0$5\0$6\0$7\0$8\0$9\0"
"$R0\0$R1\0$R2\0$R3\0$R4\0$R5\0$R6\0$R7\0$R8\0$R9\0"
"$CMDLINE\0$INSTDIR\0$OUTDIR\0$EXEDIR\0$LANGUAGE\0";
int res = line.gettoken_enum(token, usrvars);
// Added by ramon 3 jun 2003
#ifdef NSIS_SUPPORT_NAMED_USERVARS
if ( res < 0 )
{
char *p = line.gettoken_str(token);
if ( *p == '$' && *(p+1) == '[' )
{
char *pUserVarName = (char *)p+2;
while ( *pUserVarName )
{
if ( *pUserVarName == ']' )
{
*pUserVarName='\0';
int idxUserVar = m_UserVarNames.get((char*)p+2);
*pUserVarName=']'; // restore
if ( idxUserVar >= 0 )
{
res=idxUserVar+USER_VARS_COUNT; // User named variable;
}
break;
}
pUserVarName++;
}
}
}
return line.gettoken_enum(token, usrvars);
#endif
return res;
}

View file

@ -10,6 +10,7 @@ using namespace std;
#include "lang.h"
#include "ResourceEditor.h"
#include "ResourceVersionInfo.h"
#include "uservars.h"
#include "exehead/fileform.h"
#include "exehead/config.h"
@ -173,7 +174,7 @@ class CEXEBuild {
int GetUserVarIndex(LineParser &line, int token);
// Added by ramon 3 jun 2003
#ifdef NSIS_SUPPORT_NAMED_USERVARS
LangStringList m_UserVarNames;
UserVarsStringList m_UserVarNames;
int DeclaredUserVar(const char *VarName);
#endif
@ -214,7 +215,6 @@ class CEXEBuild {
// Added by ramon 6 jun 2003
#ifdef NSIS_SUPPORT_VERSION_INFO
CResourceVersionInfo rVersionInfo;
int version_codePage, version_lang;
char version_product_v[1024];
#endif

View file

@ -515,7 +515,7 @@ DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove, DWORD dwMoveMethod);
// $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value.
// Added by ramon 3 jun 2003
#ifdef NSIS_SUPPORT_NAMED_USERVARS
#define VAR_CODES_START (256 - 38)
#define VAR_CODES_START 250
#else
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
#define VAR_CODES_START (256 - 37)

View file

@ -400,6 +400,7 @@ char * NSISCALL process_string(const char *in)
while (*in && out - ps_tmpbuf < NSIS_MAX_STRLEN)
{
int nVarIdx = (unsigned char)*in++;
#ifndef NSIS_SUPPORT_NAMED_USERVARS
if (nVarIdx < VAR_CODES_START)
{
*out++ = nVarIdx;
@ -443,24 +444,9 @@ char * NSISCALL process_string(const char *in)
case VAR_CODES_START + 24: // EXEDIR
case VAR_CODES_START + 25: // LANGUAGE
case VAR_CODES_START + 26: // PLUGINSDIR
#ifdef NSIS_SUPPORT_NAMED_USERVARS
case VAR_CODES_START + 36: // NAMED USER VARS
{
if ( nVarIdx == (VAR_CODES_START + 36) )
{
//char Buf[200];
nVarIdx = *(WORD*)in & 0x0FFF; in+=sizeof(WORD);
//wsprintf(Buf, "Request var index %d", nVarIdx);
//MessageBox(0,Buf,0,0);
}
else
nVarIdx = nVarIdx - (VAR_CODES_START + 1);
mystrcpy(out, g_usrvars[nVarIdx]);
}
#else
mystrcpy(out, g_usrvars[nVarIdx - (VAR_CODES_START + 1)]);
break;
#endif
case VAR_CODES_START + 27: // PROGRAMFILES
smwcvesf[41]=0;
myRegGetStr(HKEY_LOCAL_MACHINE, smwcvesf, "ProgramFilesDir", out);
@ -522,27 +508,112 @@ char * NSISCALL process_string(const char *in)
GetSystemDirectory(out, NSIS_MAX_STRLEN);
break;
#ifdef NSIS_SUPPORT_NAMED_USERVARS
#if USER_VARS_COUNT + MAX_NAMED_USER_VARS > 0x0FFF
#error "Too many named variables! Decrease MAX_NAMED_USER_VARS"
#endif
#if VAR_CODES_START + 36 >= 255
#error "Too many variables! Extend VAR_CODES_START!"
#endif
#else
#if VAR_CODES_START + 35 >= 255
#error "Too many variables! Extend VAR_CODES_START!"
#endif
#endif
} // switch
// validate the directory name
if (nVarIdx > 21+VAR_CODES_START && nVarIdx < VAR_CODES_START + 36 ) { // only if not $0 to $R9, $CMDLINE, or $HWNDPARENT
if (nVarIdx > 21+VAR_CODES_START ) { // only if not $0 to $R9, $CMDLINE, or $HWNDPARENT
// ($LANGUAGE can't have trailing backslash anyway...)
validate_filename(out);
}
out+=mystrlen(out);
} // >= VAR_CODES_START
#else
if (nVarIdx == 255)
{
*out++ = *in++;
}
else if (nVarIdx != VAR_CODES_START)
{
*out++ = nVarIdx;
}
else
{
DWORD f;
static char smwcvesf[]="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
nVarIdx = (*(WORD*)in & 0x0FFF)-1; in+=sizeof(WORD);
switch (nVarIdx) // The order of this list must match that in ..\strlist.cpp (err, build.cpp -J)
{
case 26: // PROGRAMFILES
smwcvesf[41]=0;
myRegGetStr(HKEY_LOCAL_MACHINE, smwcvesf, "ProgramFilesDir", out);
if (!*out)
mystrcpy(out, "C:\\Program Files");
break;
case 27: // SMPROGRAMS
case 28: // SMSTARTUP
case 29: // DESKTOP
case 30: // STARTMENU
case 31: // QUICKLAUNCH
{
static const char *tab[]={
"Programs",
"Startup",
"Desktop",
"Start Menu",
"AppData"
};
static char name[20]="Common ";
const char *name_=tab[nVarIdx-27];
mystrcpy(name+7,name_);
f=g_flags.all_user_var & (nVarIdx != 31);
again:
smwcvesf[41]='\\';
myRegGetStr(f?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
smwcvesf,
f?name:name_,out);
if (!out[0])
{
if (f)
{
f=0; goto again;
}
mystrcpy(out,temp_directory);
}
if (nVarIdx == 31) {
lstrcat(out, "\\Microsoft\\Internet Explorer\\Quick Launch");
f = GetFileAttributes(out);
if (f != (DWORD)-1 && (f & FILE_ATTRIBUTE_DIRECTORY))
break;
}
else break;
}
case 32: // TEMP
mystrcpy(out,temp_directory);
break;
case 33: // WINDIR
GetWindowsDirectory(out, NSIS_MAX_STRLEN);
break;
case 34: // SYSDIR
GetSystemDirectory(out, NSIS_MAX_STRLEN);
break;
case 35: // HWNDPARENT
myitoa(out, (unsigned int)g_hwnd);
break;
default:
mystrcpy(out, g_usrvars[nVarIdx]);
break;
} // switch
// validate the directory name
if (nVarIdx > 21 && nVarIdx < 36 ) { // only if not $0 to $R9, $CMDLINE, or $HWNDPARENT and not great than $SYSDIR
// ($LANGUAGE can't have trailing backslash anyway...)
validate_filename(out);
}
out+=mystrlen(out);
} // == VAR_CODES_START
#endif
} // while
*out = 0;
return ps_tmpbuf;
@ -608,4 +679,4 @@ void NSISCALL log_write(int close)
}
}
}
#endif
#endif

View file

@ -69,8 +69,8 @@ LINK32=link.exe
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /Ob2 /D "_CONSOLE" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /FD /c
# SUBTRACT BASE CPP /Fr /YX /Yc /Yu
# ADD CPP /nologo /MLd /W3 /GX /ZI /Od /D "_CONSOLE" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /FD /c
# SUBTRACT CPP /Fr /YX /Yc /Yu
# ADD CPP /nologo /MLd /W3 /GX /ZI /Od /D "_CONSOLE" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fr /FD /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@ -260,6 +260,10 @@ SOURCE=.\tokens.h
# End Source File
# Begin Source File
SOURCE=.\uservars.h
# End Source File
# Begin Source File
SOURCE=.\util.h
# End Source File
# End Group

View file

@ -1968,8 +1968,15 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
uDefCodePage = newNLF->m_uCodePage;
}
build_nlfs.push_back(newNLF);
LANGID lang = newNLF->m_wLangId;
GetTable(lang);
StringTable * Table = GetTable(newNLF->m_wLangId);
for (i = 0; i < build_nlfs.size(); i++) {
if (build_nlfs[i]->m_wLangId == Table->lang_id) {
Table->nlf = build_nlfs[i];
break;
}
}
last_used_lang = newNLF->m_wLangId;
// define LANG_LangName as "####" (lang id)
// for example ${LANG_ENGLISH} = 1033
@ -4391,8 +4398,9 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
#ifdef NSIS_SUPPORT_VERSION_INFO
case TOK_VI_ADDKEY:
{
char *pKey = line.gettoken_str(1);
char *pValue = line.gettoken_str(2);
LANGID LangID = line.gettoken_int(1);
char *pKey = line.gettoken_str(2);
char *pValue = line.gettoken_str(3);
if ( !(*pKey) )
{
ERROR_MSG("Error: empty name for version info key!\n");
@ -4400,64 +4408,27 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
}
else
{
SCRIPT_MSG("%s = \"%s\"=\"%s\" \n",line.gettoken_str(0), line.gettoken_str(1), line.gettoken_str(2));
rVersionInfo.SetKeyValue(pKey, pValue);
return PS_OK;
}
}
case TOK_VI_ADDTRANSLATION:
{
int s1, s2;
int language = line.gettoken_int(1, &s1);
int codepage = line.gettoken_int(2, &s2);
if ( !s1 || !s2 )
PRINTHELP()
else
{
if ( !rVersionInfo.IsValidCodePage(codepage) )
{
ERROR_MSG("Error: invalid codepage id %d!\n", codepage);
return PS_ERROR;
}
if ( !IsValidLocale(language, LCID_SUPPORTED) )
{
ERROR_MSG("Error: invalid language id %d!\n", language);
return PS_ERROR;
}
rVersionInfo.AddTranslation(codepage, language);
return PS_OK;
}
}
SCRIPT_MSG("%s: \"%s\" \"%s\" \"%s\"\n", line.gettoken_str(0), line.gettoken_str(1), line.gettoken_str(2), line.gettoken_str(3));
StringTable *strTable = GetTable(LangID);
if ( line.gettoken_int(1) == 0 && !strTable->nlf )
warning("%s: \"%s\" language not loaded, using default \"1033-English\". (%s:%d)", line.gettoken_str(0), line.gettoken_str(1), curfilename,linecnt);
if ( rVersionInfo.SetKeyValue(LangID, strTable->nlf ? strTable->nlf->m_uCodePage : 1252 /*English US*/, pKey, pValue) )
{
ERROR_MSG("%s: \"%s\" \"%04d-%s\" already defined!\n",line.gettoken_str(0), line.gettoken_str(2), LangID, strTable->nlf ? strTable->nlf->m_szName : LangID == 1033 ? "English" : "???");
return PS_ERROR;
}
return make_sure_not_in_secorfunc(line.gettoken_str(0));
}
}
case TOK_VI_SETPRODUCTVERSION:
strcpy(version_product_v, line.gettoken_str(1));
return PS_OK;
case TOK_VI_SETVERSIONLANGUAGE:
{
int s1, s2;
int language = line.gettoken_int(1, &s1);
int codepage = line.gettoken_int(2, &s2);
if ( !s1 || !s2 )
PRINTHELP()
else
if ( version_product_v[0] )
{
if ( !rVersionInfo.IsValidCodePage(codepage) )
{
ERROR_MSG("Error: invalid codepage id %d!\n", codepage);
ERROR_MSG("Error: %s already defined!\n", line.gettoken_str(0));
return PS_ERROR;
}
if ( !IsValidLocale(language, LCID_SUPPORTED) )
{
ERROR_MSG("Error: invalid language id %d!\n", language);
return PS_ERROR;
}
char Buf[10];
sprintf(Buf, "%04x%04x", language, codepage);
rVersionInfo.SetVersionInfoLang(Buf);
return PS_OK;
}
}
strcpy(version_product_v, line.gettoken_str(1));
return make_sure_not_in_secorfunc(line.gettoken_str(0));
#else
case TOK_VI_ADDKEY:

View file

@ -278,7 +278,7 @@ class SortedStringListND // no delete - can be placed in GrowBuf
{
int where;
T newstruct={0,};
int pos=find(name,case_sensitive,1,&where);
int pos=find(name,-1,case_sensitive,1,&where);
if (pos==-1) return alwaysreturnpos ? where : -1;
newstruct.name=strings.add(name,strlen(name)+1);
@ -292,7 +292,8 @@ class SortedStringListND // no delete - can be placed in GrowBuf
// returns -1 if not found, position if found
// if returnbestpos=1 returns -1 if found, best pos to insert if not found
int find(const char *str, int case_sensitive=0, int returnbestpos=0, int *where=0)
// if n_chars equal to -1 all string is tested
int find(const char *str, size_t n_chars=-1, int case_sensitive=0, int returnbestpos=0, int *where=0)
{
T *data=(T *)gr.get();
int ul=gr.getlen()/sizeof(T);
@ -302,10 +303,22 @@ class SortedStringListND // no delete - can be placed in GrowBuf
while (ul > ll)
{
int res;
if (case_sensitive)
res=strcmp(str, (char*)strings.get() + data[nextpos].name);
const char *pCurr = (char*)strings.get() + data[nextpos].name;
if (n_chars == -1 || n_chars != strlen(pCurr) )
{
if (case_sensitive)
res=strcmp(str, pCurr);
else
res=stricmp(str, pCurr);
}
else
res=stricmp(str, (char*)strings.get() + data[nextpos].name);
{
if (case_sensitive)
res=strncmp(str, pCurr, n_chars);
else
res=strnicmp(str, pCurr, n_chars);
}
if (res==0)
{
if (where) *where = nextpos;

View file

@ -230,9 +230,7 @@ static tokenType tokenlist[TOK__LAST] =
// Added by ramon 3 jun 2003
{TOK_DEFVAR,"dim",1,0,"VarName"},
// Added by ramon 6 jun 2003
{TOK_VI_ADDKEY,"VIAddVersionKey", 2, 0, "[keyname] [value]"},
{TOK_VI_ADDTRANSLATION,"VIAddTranslation", 2, 0, "[short language id] [short codepage id]"},
{TOK_VI_SETVERSIONLANGUAGE,"VISetVersionLanguage", 2, 0, "[short language id] [short codepage id]"},
{TOK_VI_ADDKEY,"VIAddVersionKey", 3, 0, "lang_id keyname value"},
{TOK_VI_SETPRODUCTVERSION,"VIProductVersion", 1, 0, "[version string X.X.X.X]"},
};

View file

@ -217,9 +217,7 @@ enum
// Added by ramon 3 jun 2003
TOK_DEFVAR,
TOK_VI_ADDKEY,
TOK_VI_ADDTRANSLATION,
TOK_VI_SETPRODUCTVERSION,
TOK_VI_SETVERSIONLANGUAGE,
TOK__LAST,
TOK__PLUGINCOMMAND

27
Source/uservars.h Normal file
View file

@ -0,0 +1,27 @@
// uservars.h by Ramon 10 Jun 2003
#ifndef ___USERVARS___H_____
#define ___USERVARS___H_____
#ifdef NSIS_SUPPORT_NAMED_USERVARS
#include "Lang.h"
class UserVarsStringList : public LangStringList
{
public:
UserVarsStringList()
{
}
~UserVarsStringList() { }
int get(char *name, size_t n_chars = -1)
{
int v=SortedStringListND<struct langstring>::find(name, n_chars);
if (v==-1) return -1;
return (((struct langstring*)gr.get())[v].index);
}
};
#endif //NSIS_SUPPORT_NAMED_USERVARS
#endif