From ab91077049bd7ddf9a634d7774181cae56aef69f Mon Sep 17 00:00:00 2001 From: ramon18 Date: Tue, 17 Jun 2003 23:59:13 +0000 Subject: [PATCH] Dynamic allocation of needed user variables (exehead grew 512 bytes). Independed user vars in uninstaller and installer git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2656 212acab6-be3b-0410-9dea-997c60f758d6 --- Examples/UserVars.nsi | 24 ++++++++- Source/build.cpp | 100 ++++++++++++++++++++++++++++---------- Source/build.h | 2 + Source/exehead/Main.c | 79 ++++++++++++++++-------------- Source/exehead/config.h | 2 + Source/exehead/fileform.c | 18 ++++++- Source/exehead/fileform.h | 4 ++ Source/exehead/state.h | 28 +++++++---- Source/exehead/util.c | 26 +++++----- Source/script.cpp | 6 ++- 10 files changed, 197 insertions(+), 92 deletions(-) diff --git a/Examples/UserVars.nsi b/Examples/UserVars.nsi index 673f676d..06076946 100644 --- a/Examples/UserVars.nsi +++ b/Examples/UserVars.nsi @@ -14,12 +14,17 @@ ;General OutFile "UserVars.exe" ShowInstDetails nevershow + InstallDir "$PROGRAMFILES\Test UserVars" ;-------------------------------- ;Pages + !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + ;-------------------------------- ;Languages @@ -28,6 +33,7 @@ ;-------------------------------- ; Declaration of User Variables with command DIM, allowed charaters for variables names : [a-z][A-Z][0-9] and '_' + DIM "un.Info" ; this one can only be used in uninstaller methods DIM "Name" DIM "Serial" @@ -39,8 +45,22 @@ Section "Dummy Section" SecCopyUI StrCpy $0 "Admin" StrCpy "$Name" $0 StrCpy "$Serial" "12345" + MessageBox MB_OK "User Name: $Name: $\n$\nSerial Number: $Serial" - MessageBox MB_OK "User Name: $Name$\n$\nSerial Number: $Serial" - + CreateDirectory $INSTDIR + WriteUninstaller "$INSTDIR\Uninst.exe" SectionEnd + +Function un.OnUninstSuccess + HideWindow + MessageBox MB_OK "$un.Info" +FunctionEnd + +Section "Uninstall" + + StrCpy $un.Info "${MUI_PRODUCT} ${MUI_VERSION} uninstalled successfully." + Delete "$INSTDIR\Uninst.exe" + RmDir $INSTDIR + +SectionEnd diff --git a/Source/build.cpp b/Source/build.cpp index c3b5e0d1..5dab901b 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -15,7 +15,7 @@ bool isSimpleChar(char ch) { - return (ch == '_' ) || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); + return (ch == '.' ) || (ch == '_' ) || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); } void CEXEBuild::define(const char *p, const char *v) @@ -33,6 +33,9 @@ CEXEBuild::~CEXEBuild() CEXEBuild::CEXEBuild() { +#ifdef NSIS_SUPPORT_NAMED_USERVARS + b_abort_compile=false; +#endif linecnt = 0; fp = 0; curfilename = 0; @@ -373,29 +376,47 @@ CEXEBuild::CEXEBuild() for ( int i = 0; i < 10; i++ ) // 0 - 9 { sprintf(Aux, "%d", i); - DeclaredUserVar(Aux); + m_UserVarNames.add(Aux); + m_UnUserVarNames.add(Aux); } for ( i = 0; i < 10; i++ ) // 10 - 19 { sprintf(Aux, "R%d", i); - DeclaredUserVar(Aux); + m_UserVarNames.add(Aux); + m_UnUserVarNames.add(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 + m_UserVarNames.add("CMDLINE"); // 20 everything before here doesn't have trailing slash removal + m_UnUserVarNames.add("CMDLINE"); + m_UserVarNames.add("INSTDIR"); // 21 + m_UnUserVarNames.add("INSTDIR"); + m_UserVarNames.add("OUTDIR"); // 22 + m_UnUserVarNames.add("OUTDIR"); + m_UserVarNames.add("EXEDIR"); // 23 + m_UnUserVarNames.add("EXEDIR"); + m_UserVarNames.add("LANGUAGE"); // 24 + m_UnUserVarNames.add("LANGUAGE"); + m_UserVarNames.add("PLUGINSDIR"); // 25 + m_UnUserVarNames.add("PLUGINSDIR"); + m_UserVarNames.add("PROGRAMFILES"); // 26 + m_UnUserVarNames.add("PROGRAMFILES"); + m_UserVarNames.add("SMPROGRAMS"); // 27 + m_UnUserVarNames.add("SMPROGRAMS"); + m_UserVarNames.add("SMSTARTUP"); // 28 + m_UnUserVarNames.add("SMSTARTUP"); + m_UserVarNames.add("DESKTOP"); // 29 + m_UnUserVarNames.add("DESKTOP"); + m_UserVarNames.add("STARTMENU"); // 30 + m_UnUserVarNames.add("STARTMENU"); + m_UserVarNames.add("QUICKLAUNCH"); // 31 + m_UnUserVarNames.add("QUICKLAUNCH"); + m_UserVarNames.add("TEMP"); // 32 + m_UnUserVarNames.add("TEMP"); + m_UserVarNames.add("WINDIR"); // 33 + m_UnUserVarNames.add("WINDIR"); + m_UserVarNames.add("SYSDIR"); // 34 everything after here doesn't have trailing slash removal + m_UnUserVarNames.add("SYSDIR"); + m_UserVarNames.add("HWNDPARENT"); // 35 + m_UnUserVarNames.add("HWNDPARENT"); #endif } @@ -422,7 +443,7 @@ int CEXEBuild::preprocess_string(char *out, const char *in) #endif { #ifndef NSIS_SUPPORT_NAMED_USERVARS - static const char VarNames[] = + static const char VarNames[] = "HWNDPARENT\0" // 0 "0\0" // 1 "1\0" // 2 @@ -462,7 +483,7 @@ int CEXEBuild::preprocess_string(char *out, const char *in) "SYSDIR\0" // 35 ; #endif - + const char *p=in; while (*p) { @@ -544,7 +565,8 @@ int CEXEBuild::preprocess_string(char *out, const char *in) while ( pUserVarName > p ) { const char * Debug = p-(pUserVarName-p); - int idxUserVar = m_UserVarNames.get((char*)p, pUserVarName-p); + + int idxUserVar = uninstall_mode ? m_UnUserVarNames.get((char*)p, pUserVarName-p) : m_UserVarNames.get((char*)p, pUserVarName-p); if ( idxUserVar >= 0 ) { *out++=(unsigned int)VAR_CODES_START; // Named user variable; @@ -2015,6 +2037,9 @@ int CEXEBuild::write_output(void) installinfo_compressed=ihd.getlen(); fh.length_of_header=hdrcomp.getlen(); +#ifdef NSIS_SUPPORT_NAMED_USERVARS + fh.length_of_uservars=m_UserVarNames.getnum()*sizeof(NSIS_STRING); +#endif } @@ -2301,6 +2326,9 @@ int CEXEBuild::uninstall_generate() set_uninstall_mode(1); fh.length_of_header=udata.getlen(); +#ifdef NSIS_SUPPORT_NAMED_USERVARS + fh.length_of_uservars=m_UnUserVarNames.getnum()*sizeof(NSIS_STRING); +#endif int err=add_data((char*)udata.get(),udata.getlen(),&uhd); set_uninstall_mode(0); if (err < 0) return PS_ERROR; @@ -2712,8 +2740,11 @@ int CEXEBuild::DeclaredUserVar(const char *szVarName) } } - m_UserVarNames.add(szVarName); - if ( m_UserVarNames.getnum() > MAX_NAMED_USER_VARS ) + if ( !strnicmp(szVarName,"un.",3) ) + m_UnUserVarNames.add(szVarName); + else + m_UserVarNames.add(szVarName); + if ( m_UserVarNames.getnum() > MAX_NAMED_USER_VARS || m_UnUserVarNames.getnum() > MAX_NAMED_USER_VARS ) { ERROR_MSG("Error: too many user variables declared!\n"); return PS_ERROR; @@ -2729,13 +2760,30 @@ int CEXEBuild::GetUserVarIndex(LineParser &line, int token) char *p = line.gettoken_str(token); if ( *p == '$' && *(p+1) ) { - int idxUserVar = m_UserVarNames.get((char *)p+1); + int idxUserVar = uninstall_mode ? m_UnUserVarNames.get((char *)p+1) : m_UserVarNames.get((char *)p+1); if ( idxUserVar >= 0 ) { - return idxUserVar; + return idxUserVar; + } + else + { + // Show error info to help developer + idxUserVar = uninstall_mode ? m_UserVarNames.get((char *)p+1) : m_UnUserVarNames.get((char *)p+1); + if ( idxUserVar >= 0 ) + { + if (!strnicmp(p+1,"un.",3) && !uninstall_mode ) { + b_abort_compile=true; + ERROR_MSG("Installer variables names can't start with un. (%s)! (%s:%d)\n", p+1, curfilename, linecnt); + } + if (strnicmp(p+1,"un.",3) && uninstall_mode ) { + b_abort_compile=true; + ERROR_MSG("Uninstaller variables names must start with un. (%s)! (%s:%d)\n", p+1, curfilename, linecnt); + } + } } } 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" diff --git a/Source/build.h b/Source/build.h index 91f22166..ee78da5c 100644 --- a/Source/build.h +++ b/Source/build.h @@ -198,7 +198,9 @@ class CEXEBuild { int GetUserVarIndex(LineParser &line, int token); // Added by ramon 3 jun 2003 #ifdef NSIS_SUPPORT_NAMED_USERVARS + bool b_abort_compile; UserVarsStringList m_UserVarNames; + UserVarsStringList m_UnUserVarNames; int DeclaredUserVar(const char *VarName); #endif diff --git a/Source/exehead/Main.c b/Source/exehead/Main.c index 631221d2..355bddf0 100644 --- a/Source/exehead/Main.c +++ b/Source/exehead/Main.c @@ -98,9 +98,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, #ifdef NSIS_CONFIG_VISIBLE_SUPPORT unsigned int verify_time=GetTickCount()+1000; #endif - char *cmdline=state_command_line; + char *realcmds; char seekchar=' '; + char *cmdline; +#ifdef NSIS_SUPPORT_NAMED_USERVARS + g_usrvars = (NSIS_STRING*)my_GlobalAlloc(USER_VARS_COUNT*sizeof(NSIS_STRING)); +#endif InitCommonControls(); @@ -108,40 +112,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, lstrcpyn(state_command_line,GetCommandLine(),NSIS_MAX_STRLEN); - if (*cmdline == '\"') seekchar = *cmdline++; - - while (*cmdline && *cmdline != seekchar) cmdline=CharNext(cmdline); - cmdline=CharNext(cmdline); - realcmds=cmdline; - - for (;;) - { - // skip over any spaces - while (*cmdline == ' ') cmdline=CharNext(cmdline); - if (cmdline[0] != '/') break; - cmdline++; - -#define END_OF_ARG(c) (((c)|' ')==' ') - -#if defined(NSIS_CONFIG_VISIBLE_SUPPORT) && defined(NSIS_CONFIG_SILENT_SUPPORT) - if (cmdline[0] == 'S' && END_OF_ARG(cmdline[1])) silent++; -#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT -#ifdef NSIS_CONFIG_CRC_SUPPORT - if (*(DWORD*)cmdline == CHAR4_TO_DWORD('N','C','R','C') && END_OF_ARG(cmdline[4])) no_crc++; -#endif//NSIS_CONFIG_CRC_SUPPORT - - if (*(WORD*)cmdline == CHAR2_TO_WORD('D','=')) - { - cmdline[-2]=0; // keep this from being passed to uninstaller if necessary - mystrcpy(state_install_directory,cmdline+2); - cmdline=""; // prevent further processing of cmdline - break; // not necessary, but for some reason makes smaller exe :) - } - - // skip over our parm - while (!END_OF_ARG(*cmdline)) cmdline=CharNext(cmdline); - } - mystrcpy(g_caption,_LANG_GENERIC_ERROR); g_hInstance=GetModuleHandle(NULL); @@ -269,14 +239,49 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, } if (m_Err) goto end; + cmdline = state_command_line; + if (*cmdline == '\"') seekchar = *cmdline++; + + while (*cmdline && *cmdline != seekchar) cmdline=CharNext(cmdline); + cmdline=CharNext(cmdline); + realcmds=cmdline; + + for (;;) + { + // skip over any spaces + while (*cmdline == ' ') cmdline=CharNext(cmdline); + if (cmdline[0] != '/') break; + cmdline++; + +#define END_OF_ARG(c) (((c)|' ')==' ') + +#if defined(NSIS_CONFIG_VISIBLE_SUPPORT) && defined(NSIS_CONFIG_SILENT_SUPPORT) + if (cmdline[0] == 'S' && END_OF_ARG(cmdline[1])) silent++; +#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (*(DWORD*)cmdline == CHAR4_TO_DWORD('N','C','R','C') && END_OF_ARG(cmdline[4])) no_crc++; +#endif//NSIS_CONFIG_CRC_SUPPORT + + if (*(WORD*)cmdline == CHAR2_TO_WORD('D','=')) + { + cmdline[-2]=0; // keep this from being passed to uninstaller if necessary + mystrcpy(state_install_directory,cmdline+2); + cmdline=""; // prevent further processing of cmdline + break; // not necessary, but for some reason makes smaller exe :) + } + + // skip over our parm + while (!END_OF_ARG(*cmdline)) cmdline=CharNext(cmdline); + } + #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT if (g_is_uninstaller) { char *p=cmdline; while (*p) p++; - while (p >= cmdline && (p[0] != '_' || p[1] != '?' || p[2] != '=')) p--; - + while (p >= cmdline && (p[0] != '_' || p[1] != '?' || p[2] != '=')) p--; + if (p >= cmdline) { *(p-1)=0; // terminate before the " _?=" diff --git a/Source/exehead/config.h b/Source/exehead/config.h index b77d13c4..884f5fbb 100644 --- a/Source/exehead/config.h +++ b/Source/exehead/config.h @@ -28,6 +28,8 @@ #define USER_VARS_COUNT 26 +typedef char NSIS_STRING[NSIS_MAX_STRLEN]; + // MAX_NAMED_USER_VARS defines the maximum of named user variables // the complier also use this value to abort if exceded // The real maximum is (0x0FFF - USER_VARS_COUNT) = 4069 diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c index 392d4bab..cea93088 100644 --- a/Source/exehead/fileform.c +++ b/Source/exehead/fileform.c @@ -52,7 +52,17 @@ int NSISCALL isheader(firstheader *h) #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT static z_stream g_inflate_stream; #endif - +/* +void DEBUG(const char* Frm, ...) +{ + char Buf[1024]; + va_list va; + va_start(va, Frm); + wvsprintf(Buf, Frm, va); + MessageBox(0, Buf, 0, 0); + va_end(va); +} +*/ const char * NSISCALL loadHeaders(void) { void *data; @@ -60,7 +70,13 @@ const char * NSISCALL loadHeaders(void) if (!ReadSelfFile((LPVOID)&h,sizeof(h)) || !isheader(&h)) return _LANG_INVALIDCRC; +#ifdef NSIS_SUPPORT_NAMED_USERVARS + //DEBUG("Needed size is : %i", h.length_of_header + h.length_of_uservars); + g_usrvars = (NSIS_STRING*)GlobalReAlloc(g_usrvars, h.length_of_header + h.length_of_uservars, GMEM_MOVEABLE); + data = (void*)(g_usrvars[0]+h.length_of_uservars); +#else data=(void*)my_GlobalAlloc(h.length_of_header); +#endif #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT inflateInit(&g_inflate_stream); diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 1fedfd74..cd2a8e2c 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -204,6 +204,10 @@ typedef struct // these point to the header+sections+entries+stringtable in the datablock int length_of_header; +#ifdef NSIS_SUPPORT_NAMED_USERVARS + // this store the sized needed to store all user vars + int length_of_uservars; +#endif // this specifies the length of all the data (including the firstheader and CRC) int length_of_all_following_data; diff --git a/Source/exehead/state.h b/Source/exehead/state.h index acb05354..6fa90a76 100644 --- a/Source/exehead/state.h +++ b/Source/exehead/state.h @@ -1,16 +1,24 @@ extern char temp_directory[NSIS_MAX_STRLEN]; #ifdef NSIS_SUPPORT_NAMED_USERVARS -extern char g_usrvars[MAX_NAMED_USER_VARS+USER_VARS_COUNT][NSIS_MAX_STRLEN]; + extern NSIS_STRING *g_usrvars; + #define state_command_line g_usrvars[20] + #define state_install_directory g_usrvars[21] + #define state_output_directory g_usrvars[22] + #define state_exe_directory g_usrvars[23] + #define state_language g_usrvars[24] + #ifdef NSIS_CONFIG_PLUGIN_SUPPORT + #define state_plugins_dir g_usrvars[25] + #endif #else -extern char g_usrvars[USER_VARS_COUNT][NSIS_MAX_STRLEN]; -#endif -extern char *state_command_line; -extern char *state_install_directory; -extern char *state_output_directory; -extern char *state_exe_directory; -extern char *state_language; -#ifdef NSIS_CONFIG_PLUGIN_SUPPORT -extern char *state_plugins_dir; + extern char g_usrvars[USER_VARS_COUNT][NSIS_MAX_STRLEN]; + extern char *state_command_line; + extern char *state_install_directory; + extern char *state_output_directory; + extern char *state_exe_directory; + extern char *state_language; + #ifdef NSIS_CONFIG_PLUGIN_SUPPORT + extern char *state_plugins_dir; + #endif #endif extern char g_caption[NSIS_MAX_STRLEN*2]; diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 0d30d5b9..0baf1c48 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -15,19 +15,18 @@ char g_log_file[1024]; #endif char temp_directory[NSIS_MAX_STRLEN]; - #ifdef NSIS_SUPPORT_NAMED_USERVARS -char g_usrvars[MAX_NAMED_USER_VARS+USER_VARS_COUNT][NSIS_MAX_STRLEN]; + NSIS_STRING *g_usrvars; #else -char g_usrvars[USER_VARS_COUNT][NSIS_MAX_STRLEN]; -#endif -char *state_command_line=g_usrvars[20]; -char *state_install_directory=g_usrvars[21]; -char *state_output_directory=g_usrvars[22]; -char *state_exe_directory=g_usrvars[23]; -char *state_language=g_usrvars[24]; -#ifdef NSIS_CONFIG_PLUGIN_SUPPORT -char *state_plugins_dir=g_usrvars[25]; + char g_usrvars[USER_VARS_COUNT][NSIS_MAX_STRLEN]; + char *state_command_line=g_usrvars[20]; + char *state_install_directory=g_usrvars[21]; + char *state_output_directory=g_usrvars[22]; + char *state_exe_directory=g_usrvars[23]; + char *state_language=g_usrvars[24]; + #ifdef NSIS_CONFIG_PLUGIN_SUPPORT + char *state_plugins_dir=g_usrvars[25]; + #endif #endif HANDLE g_hInstance; @@ -611,8 +610,6 @@ char * NSISCALL process_string(const char *in) 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 @@ -624,9 +621,8 @@ char * NSISCALL process_string(const char *in) #ifdef NSIS_SUPPORT_LANG_IN_STRINGS else if ( nVarIdx == LANG_CODES_START ) { - char *p; nVarIdx = *(short*)in; in+=sizeof(WORD); - p = process_string(GetStringFromStringTab(nVarIdx), out-ps_tmpbuf); + process_string(GetStringFromStringTab(nVarIdx), out-ps_tmpbuf); out+=mystrlen(out); } #endif diff --git a/Source/script.cpp b/Source/script.cpp index e13bb64c..2b610865 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -164,7 +164,11 @@ int CEXEBuild::process_script(FILE *filepointer, char *filename) return ret; } -#define PRINTHELP() { print_help(line.gettoken_str(0)); return PS_ERROR; } +#ifdef NSIS_SUPPORT_NAMED_USERVARS + #define PRINTHELP() { if ( !b_abort_compile ) print_help(line.gettoken_str(0)); return PS_ERROR; } +#else + #define PRINTHELP() { print_help(line.gettoken_str(0)); return PS_ERROR; } +#endif int CEXEBuild::doParse(const char *str)