From 054db45f636a3948c435577e440613ca5e54a0a9 Mon Sep 17 00:00:00 2001 From: ramon18 Date: Mon, 23 Jun 2003 22:40:11 +0000 Subject: [PATCH] Special section of data for user vars, whitch allow compiler to assign the right size and no code needed in exehead for mem allocs. Warnings for unreferenced user vars. (758773) Error, if temp file not available, now directory is created if not exist. git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2673 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/ResourceEditor.cpp | 36 +++++++++++- Source/ResourceEditor.h | 1 + Source/build.cpp | 118 +++++++++++++++++++++++--------------- Source/build.h | 1 + Source/exehead/Main.c | 7 ++- Source/exehead/config.h | 30 ++++++---- Source/exehead/exec.c | 4 +- Source/exehead/fileform.c | 20 +------ Source/exehead/fileform.h | 4 -- Source/exehead/state.h | 18 +++--- Source/exehead/util.c | 22 ++++--- Source/uservars.h | 71 ++++++++++++++++++++++- 12 files changed, 227 insertions(+), 105 deletions(-) diff --git a/Source/ResourceEditor.cpp b/Source/ResourceEditor.cpp index 111df70d..1e2e6659 100644 --- a/Source/ResourceEditor.cpp +++ b/Source/ResourceEditor.cpp @@ -274,8 +274,10 @@ BYTE* CResourceEditor::Save(DWORD &dwSize) { // Refresh the headers of the sections that come after the resource section, and the data directory for (i++; i < ntHeaders->FileHeader.NumberOfSections; i++) { - sectionHeadersArray[i].PointerToRawData -= IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData; - sectionHeadersArray[i].PointerToRawData += dwRsrcSizeAligned; + if ( sectionHeadersArray[i].PointerToRawData ) { + sectionHeadersArray[i].PointerToRawData -= IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData; + sectionHeadersArray[i].PointerToRawData += dwRsrcSizeAligned; + } int secInDataDir = 0; for (unsigned int j = 0; j < ntHeaders->OptionalHeader.NumberOfRvaAndSizes; j++) if (ntHeaders->OptionalHeader.DataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress) @@ -325,6 +327,36 @@ BYTE* CResourceEditor::Save(DWORD &dwSize) { return pbNewPE; } +// This function scans exe sections and after find a match with given name +// increments it's virtual size (auto fixes image size based on section alignment, etc) +bool CResourceEditor::AddExtraVirtualSize2PESection(const char* pszSectionName, int addsize) +{ + PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders); + + // Refresh the headers of the sections that come after the resource section, and the data directory + for (int i =0; i < m_ntHeaders->FileHeader.NumberOfSections; i++) { + if ( !strcmp((LPCSTR)sectionHeadersArray[i].Name, pszSectionName) ) { + sectionHeadersArray[i].Misc.VirtualSize += addsize; + sectionHeadersArray[i].Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE; + sectionHeadersArray[i].Misc.VirtualSize = RALIGN(sectionHeadersArray[i].Misc.VirtualSize, m_ntHeaders->OptionalHeader.SectionAlignment); + // now fix any section after + for (int k=i+1; k< m_ntHeaders->FileHeader.NumberOfSections; k++, i++) { + sectionHeadersArray[k].VirtualAddress = sectionHeadersArray[i].VirtualAddress + sectionHeadersArray[i].Misc.VirtualSize; + sectionHeadersArray[k].VirtualAddress = RALIGN(sectionHeadersArray[k].VirtualAddress, m_ntHeaders->OptionalHeader.SectionAlignment); + if ( m_dwResourceSectionIndex == k ) + { + // fix the resources virtual address if it changed + m_dwResourceSectionVA = m_ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = sectionHeadersArray[k].VirtualAddress; + } + } + + return true; + } + } + + return false; +} + ////////////////////////////////////////////////////////////////////// // Private Methods ////////////////////////////////////////////////////////////////////// diff --git a/Source/ResourceEditor.h b/Source/ResourceEditor.h index 09696693..65b84d71 100644 --- a/Source/ResourceEditor.h +++ b/Source/ResourceEditor.h @@ -68,6 +68,7 @@ public: bool UpdateResource(WORD szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); BYTE* GetResource(char* szType, char* szName, LANGID wLanguage); + bool AddExtraVirtualSize2PESection(const char* pszSectionName, int addsize); BYTE* Save(DWORD &dwSize); private: diff --git a/Source/build.cpp b/Source/build.cpp index ac7d3d4c..415790b9 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -351,52 +351,53 @@ CEXEBuild::CEXEBuild() build_header.license_bg=-COLOR_BTNFACE; #ifdef NSIS_SUPPORT_NAMED_USERVARS - // Register user variables $0, $1 and so one + // Register static user variables $0, $1 and so one + // with ONE of reference count, to avoid warning on this vars char Aux[3]; for ( int i = 0; i < 10; i++ ) // 0 - 9 { sprintf(Aux, "%d", i); - m_UserVarNames.add(Aux); - m_UnUserVarNames.add(Aux); + m_UserVarNames.add(Aux,1); + m_UnUserVarNames.add(Aux,1); } for ( i = 0; i < 10; i++ ) // 10 - 19 { sprintf(Aux, "R%d", i); - m_UserVarNames.add(Aux); - m_UnUserVarNames.add(Aux); + m_UserVarNames.add(Aux,1); + m_UnUserVarNames.add(Aux,1); } - 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"); + m_UserVarNames.add("CMDLINE",1); // 20 everything before here doesn't have trailing slash removal + m_UnUserVarNames.add("CMDLINE",1); + m_UserVarNames.add("INSTDIR",1); // 21 + m_UnUserVarNames.add("INSTDIR",1); + m_UserVarNames.add("OUTDIR",1); // 22 + m_UnUserVarNames.add("OUTDIR",1); + m_UserVarNames.add("EXEDIR",1); // 23 + m_UnUserVarNames.add("EXEDIR",1); + m_UserVarNames.add("LANGUAGE",1); // 24 + m_UnUserVarNames.add("LANGUAGE",1); + m_UserVarNames.add("PLUGINSDIR",1); // 25 + m_UnUserVarNames.add("PLUGINSDIR",1); + m_UserVarNames.add("PROGRAMFILES",1); // 26 + m_UnUserVarNames.add("PROGRAMFILES",1); + m_UserVarNames.add("SMPROGRAMS",1); // 27 + m_UnUserVarNames.add("SMPROGRAMS",1); + m_UserVarNames.add("SMSTARTUP",1); // 28 + m_UnUserVarNames.add("SMSTARTUP",1); + m_UserVarNames.add("DESKTOP",1); // 29 + m_UnUserVarNames.add("DESKTOP",1); + m_UserVarNames.add("STARTMENU",1); // 30 + m_UnUserVarNames.add("STARTMENU",1); + m_UserVarNames.add("QUICKLAUNCH",1); // 31 + m_UnUserVarNames.add("QUICKLAUNCH",1); + m_UserVarNames.add("TEMP",1); // 32 + m_UnUserVarNames.add("TEMP",1); + m_UserVarNames.add("WINDIR",1); // 33 + m_UnUserVarNames.add("WINDIR",1); + m_UserVarNames.add("SYSDIR",1); // 34 everything after here doesn't have trailing slash removal + m_UnUserVarNames.add("SYSDIR",1); + m_UserVarNames.add("HWNDPARENT",1); // 35 + m_UnUserVarNames.add("HWNDPARENT",1); #endif } @@ -544,11 +545,14 @@ int CEXEBuild::preprocess_string(char *out, const char *in) while ( pUserVarName > p ) { - const char * Debug = p-(pUserVarName-p); - int idxUserVar = uninstall_mode ? m_UnUserVarNames.get((char*)p, pUserVarName-p) : m_UserVarNames.get((char*)p, pUserVarName-p); if ( idxUserVar >= 0 ) { + // Well, using variables inside string formating doens't mean + // using the variable, beacuse it will be always an empty string + // which is also memory wasting + // So the line below must be commented !?? + //uninstall_mode ? m_UnUserVarNames.inc_reference(idxUserVar): m_UserVarNames.inc_reference(idxUserVar); *out++=(unsigned int)VAR_CODES_START; // Named user variable; *(WORD*)out=((WORD)idxUserVar+1) | 0xF000; out += sizeof(WORD); @@ -1868,9 +1872,20 @@ int CEXEBuild::write_output(void) // Generate language tables if (WriteStringTables() == PS_ERROR) return PS_ERROR; +#ifdef NSIS_SUPPORT_NAMED_USERVARS + VerifyDeclaredUserVarRefs(&m_UserVarNames); + VerifyDeclaredUserVarRefs(&m_UnUserVarNames); + int MaxUserVars = max(m_UserVarNames.getnum(), m_UnUserVarNames.getnum()); + if (!res_editor->AddExtraVirtualSize2PESection(VARS_SECTION_NAME, (MaxUserVars-TOTAL_COMPATIBLE_STATIC_VARS_COUNT) * sizeof(NSIS_STRING))) + { + ERROR_MSG("Internal compiler error #12346: invalid exehead cannot find section \"%s\"!\n", VARS_SECTION_NAME); + return PS_ERROR; + } +#endif + // Save all changes to the exe header try { - close_res_editor(); + close_res_editor(); } catch (exception& err) { ERROR_MSG("\nError: %s\n", err.what()); @@ -2017,9 +2032,6 @@ 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 } @@ -2306,9 +2318,6 @@ 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; @@ -2738,11 +2747,13 @@ int CEXEBuild::GetUserVarIndex(LineParser &line, int token) #ifdef NSIS_SUPPORT_NAMED_USERVARS char *p = line.gettoken_str(token); + UserVarsStringList *pUserVarList = uninstall_mode ? &m_UnUserVarNames : &m_UserVarNames; if ( *p == '$' && *(p+1) ) { - int idxUserVar = uninstall_mode ? m_UnUserVarNames.get((char *)p+1) : m_UserVarNames.get((char *)p+1); + int idxUserVar = pUserVarList->get((char *)p+1); if ( idxUserVar >= 0 ) { + pUserVarList->inc_reference(idxUserVar); return idxUserVar; } else @@ -2772,3 +2783,16 @@ int CEXEBuild::GetUserVarIndex(LineParser &line, int token) return line.gettoken_enum(token, usrvars); #endif } + +#ifdef NSIS_SUPPORT_NAMED_USERVARS +void CEXEBuild::VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList) +{ + for ( int i = TOTAL_COMPATIBLE_STATIC_VARS_COUNT; i < pVarsStringList->getnum(); i++ ) + { + if ( !pVarsStringList->get_reference(i) ) + { + warning("Variable \"%s\" not referenced, wasting memory!", pVarsStringList->idx2name(i)); + } + } +} +#endif \ No newline at end of file diff --git a/Source/build.h b/Source/build.h index ee78da5c..4c0e4ade 100644 --- a/Source/build.h +++ b/Source/build.h @@ -202,6 +202,7 @@ class CEXEBuild { UserVarsStringList m_UserVarNames; UserVarsStringList m_UnUserVarNames; int DeclaredUserVar(const char *VarName); + void VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList); #endif // a whole bunch O data. diff --git a/Source/exehead/Main.c b/Source/exehead/Main.c index ae9163f8..50defde6 100644 --- a/Source/exehead/Main.c +++ b/Source/exehead/Main.c @@ -108,7 +108,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, InitCommonControls(); - GetTempPath(sizeof(temp_directory), temp_directory); + GetTempPath(sizeof(state_temp_dir), state_temp_dir); + CreateDirectory(state_temp_dir,NULL); lstrcpyn(state_command_line,GetCommandLine(),NSIS_MAX_STRLEN); @@ -308,7 +309,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, static char ibuf[NSIS_MAX_STRLEN]; buf2[0]='\"'; - mystrcpy(buf2+1,temp_directory); + mystrcpy(buf2+1,state_temp_dir); lstrcat(buf2,s); DeleteFile(buf2+1); // clean up after all the other ones if they are there @@ -334,7 +335,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, lstrcat(buf2,realcmds); lstrcat(buf2," _?="); lstrcat(buf2,ibuf); - hProc=myCreateProcess(buf2,temp_directory); + hProc=myCreateProcess(buf2,state_temp_dir); if (hProc) CloseHandle(hProc); else m_Err = g_errorcopyinginstall; } diff --git a/Source/exehead/config.h b/Source/exehead/config.h index 884f5fbb..c24dcfdd 100644 --- a/Source/exehead/config.h +++ b/Source/exehead/config.h @@ -26,16 +26,6 @@ // really a big deal, but not usually needed). #define NSIS_MAX_STRLEN 1024 -#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 -// But 500 variables are a more than enough (and only consume more 512kb of memory) -#define MAX_NAMED_USER_VARS 500 - // NSIS_MAX_INST_TYPES specified the maximum install types. // note that this should not exceed 32, ever. #define NSIS_MAX_INST_TYPES 32 @@ -364,6 +354,26 @@ typedef char NSIS_STRING[NSIS_MAX_STRLEN]; #define NSIS_SUPPORT_STANDARD_PREDEFINES #endif +// This is the old static var count that occupies memory +// From $0 to $PLUGINSDIR +#define USER_VARS_COUNT 26 + +#ifdef NSIS_SUPPORT_NAMED_USERVARS +// This is the total number of old static var +// From $0 to $HWNDPARENT +#define TOTAL_COMPATIBLE_STATIC_VARS_COUNT 36 + +#define VARS_SECTION_NAME ".ndata" + +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) = 4068 +#define MAX_NAMED_USER_VARS (0x0FFF - USER_VARS_COUNT) + +#endif //NSIS_SUPPORT_NAMED_USERVARS + #endif//!APSTUDIO_INVOKED #endif // NSIS_CONFIG_H diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 86190e17..35af1e32 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -367,7 +367,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) int n=100; while (n--) { - if (GetTempFileName(temp_directory,"nst",0,textout)) + if (GetTempFileName(state_temp_dir,"nst",0,textout)) return 0; } g_flags.exec_error++; @@ -1443,7 +1443,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) filebuf=(unsigned char *)my_GlobalAlloc(g_filehdrsize); if (filebuf) { - int fixoffs=0; + //int fixoffs=0; DWORD lout; SetSelfFilePointer(0,FILE_BEGIN); ReadSelfFile((char*)filebuf,g_filehdrsize); diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c index cea93088..62b8da35 100644 --- a/Source/exehead/fileform.c +++ b/Source/exehead/fileform.c @@ -52,17 +52,7 @@ 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; @@ -70,13 +60,7 @@ 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); @@ -86,7 +70,7 @@ const char * NSISCALL loadHeaders(void) { char fno[MAX_PATH]; - GetTempFileName(temp_directory,"nst",0,fno); + GetTempFileName(state_temp_dir,"nst",0,fno); dbd_hFile=CreateFile(fno,GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE,NULL); if (dbd_hFile == INVALID_HANDLE_VALUE) { diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index cd2a8e2c..1fedfd74 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -204,10 +204,6 @@ 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 6fa90a76..26089951 100644 --- a/Source/exehead/state.h +++ b/Source/exehead/state.h @@ -1,15 +1,16 @@ -extern char temp_directory[NSIS_MAX_STRLEN]; #ifdef NSIS_SUPPORT_NAMED_USERVARS - 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] + extern NSIS_STRING g_usrvars[TOTAL_COMPATIBLE_STATIC_VARS_COUNT]; + #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] + #define state_plugins_dir g_usrvars[25] #endif + #define state_temp_dir g_usrvars[32] #else + extern char temp_directory[NSIS_MAX_STRLEN]; extern char g_usrvars[USER_VARS_COUNT][NSIS_MAX_STRLEN]; extern char *state_command_line; extern char *state_install_directory; @@ -19,6 +20,7 @@ extern char temp_directory[NSIS_MAX_STRLEN]; #ifdef NSIS_CONFIG_PLUGIN_SUPPORT extern char *state_plugins_dir; #endif + #define state_temp_dir temp_directory #endif extern char g_caption[NSIS_MAX_STRLEN*2]; diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 99be0b89..420235fb 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -14,10 +14,20 @@ char g_log_file[1024]; #endif -char temp_directory[NSIS_MAX_STRLEN]; #ifdef NSIS_SUPPORT_NAMED_USERVARS - NSIS_STRING *g_usrvars; + // *** DO NOT DECLARE MORE VARIABLES INSIDE THIS PRAGMAS *** + // This will produce a special section called ".ndata" (stands for nsis data) + // this way makensis during build time, can search for this section by name + // and change the virtual size of this section + // which result in extra memory for extra variables without code to do allocation :) + // nsis then removes the "DISCARDABLE" style from section (for safe) + #pragma bss_seg( VARS_SECTION_NAME ) + NSIS_STRING g_usrvars[TOTAL_COMPATIBLE_STATIC_VARS_COUNT]; + #pragma bss_seg() + #define SECTION_VARS_RWD "/section:" ## VARS_SECTION_NAME ## ",rwd" + #pragma comment(linker, SECTION_VARS_RWD) #else + char temp_directory[NSIS_MAX_STRLEN]; char g_usrvars[USER_VARS_COUNT][NSIS_MAX_STRLEN]; char *state_command_line=g_usrvars[20]; char *state_install_directory=g_usrvars[21]; @@ -580,7 +590,7 @@ char * NSISCALL process_string(const char *in) { f=0; goto again; } - mystrcpy(out,temp_directory); + mystrcpy(out,state_temp_dir); } if (nVarIdx == 31) { @@ -592,10 +602,6 @@ char * NSISCALL process_string(const char *in) else break; } - case 32: // TEMP - mystrcpy(out,temp_directory); - break; - case 33: // WINDIR GetWindowsDirectory(out, NSIS_MAX_STRLEN); break; @@ -612,7 +618,7 @@ char * NSISCALL process_string(const char *in) mystrcpy(out, g_usrvars[nVarIdx]); } // switch // validate the directory name - if (nVarIdx > 21 && nVarIdx < 36 ) { // only if not $0 to $R9, $CMDLINE, or $HWNDPARENT and not great than $SYSDIR + if (nVarIdx > 21 && nVarIdx < TOTAL_COMPATIBLE_STATIC_VARS_COUNT ) { // only if not $0 to $R9, $CMDLINE, or $HWNDPARENT and not great than $SYSDIR // ($LANGUAGE can't have trailing backslash anyway...) validate_filename(out); } diff --git a/Source/uservars.h b/Source/uservars.h index 71d306bc..d5617642 100644 --- a/Source/uservars.h +++ b/Source/uservars.h @@ -7,19 +7,84 @@ #include "Lang.h" -class UserVarsStringList : public LangStringList +struct uservarstring { + int name; + int index; + int pos; + int reference; +}; + +class UserVarsStringList : public SortedStringListND { public: UserVarsStringList() { + index = 0; } ~UserVarsStringList() { } + int add(const char *name, int ref_count = 0 ) + { + int pos=SortedStringListND::add(name); + if (pos == -1) return -1; + + ((struct uservarstring*)gr.get())[pos].index = index; + ((struct uservarstring*)gr.get())[pos].pos = pos; + ((struct uservarstring*)gr.get())[pos].reference = ref_count; + + int temp = index; + index++; + + return temp; + } + int get(char *name, size_t n_chars = -1) { - int v=SortedStringListND::find(name, n_chars); + int v=SortedStringListND::find(name, n_chars); if (v==-1) return -1; - return (((struct langstring*)gr.get())[v].index); + return (((struct uservarstring*)gr.get())[v].index); + } + + int getnum() + { + return index; + } + + int get_reference(int idx) + { + int pos=get_internal_idx(idx); + if (pos==-1) return -1; + return (((struct uservarstring*)gr.get())[pos].reference); + } + + int inc_reference(int idx) + { + int pos=get_internal_idx(idx); + ((struct uservarstring*)gr.get())[pos].reference++; + return (((struct uservarstring*)gr.get())[pos].reference)-1; + } + + char *idx2name(int idx) + { + int pos=get_internal_idx(idx); + if (pos==-1) return NULL; + struct uservarstring *data=(struct uservarstring *)gr.get(); + return ((char*)strings.get() + data[pos].name); + } + + private: + int index; + int get_internal_idx(int idx) + { + struct uservarstring *data=(struct uservarstring *)gr.get(); + for (int i = 0; i < index; i++) + { + if (data[i].index == idx) + { + return i; + } + } + return -1; } }; #endif //NSIS_SUPPORT_NAMED_USERVARS