diff --git a/Docs/src/compiler.but b/Docs/src/compiler.but index 7bf912d6..62241753 100644 --- a/Docs/src/compiler.but +++ b/Docs/src/compiler.but @@ -167,7 +167,7 @@ This command creates a temporary file. It puts its path into a define, named \e{ \S1{ppgetdllversion} !getdllversion -\c [/noerrors] [/packed] localfilename define_basename +\c [/noerrors] [/packed] [/productversion] localfilename define_basename This is similar to \R{getdllversionlocal}{GetDLLVersionLocal}, only it stores the version number in defines and can therefore be used anywhere, not just inside functions and sections. /packed returns the information in two DWORDs. diff --git a/Docs/src/generalpurpose.but b/Docs/src/generalpurpose.but index 5917eb97..55b0af0a 100644 --- a/Docs/src/generalpurpose.but +++ b/Docs/src/generalpurpose.but @@ -61,7 +61,7 @@ Gets the Windows version as reported by GetVersionEx. WinVer.nsh is the preferre \S2{getdllversion} GetDLLVersion -\c filename user_var(high dword output) user_var(low dword output) +\c [/ProductVersion] filename user_var(high dword output) user_var(low dword output) Gets the version information from the DLL (or any other executable containing version information) in "filename". Sets the user output variables with the high and low dwords of version information on success; on failure the outputs are empty and the error flag is set. The following example reads the DLL version and copies a human readable version of it into $0: @@ -74,7 +74,7 @@ Gets the version information from the DLL (or any other executable containing ve \S2{getdllversionlocal} GetDLLVersionLocal -\c localfilename user_var(high dword output) user_var(low dword output) +\c [/ProductVersion] localfilename user_var(high dword output) user_var(low dword output) This is similar to \R{getdllversion}{GetDLLVersion}, only it acts on the system building the installer (it actually compiles into two \R{StrCpy}{StrCpy} commands). Sets the two output variables with the DLL version information of the DLL on the build system. Use \R{ppgetdllversion}{!getdllversion} if you need to use the values with \R{viproductversion}{VIProductVersion}. diff --git a/Docs/src/history.but b/Docs/src/history.but index 93ad4ec3..e8e04d29 100644 --- a/Docs/src/history.but +++ b/Docs/src/history.but @@ -18,6 +18,8 @@ Released on ???? ??th, 20?? \b Added \cw{$USER..} and \cw{$COMMON..} alias constants +\b Added GetDllVersion /ProductVersion switch + \b Added \R{getwinver}{GetWinVer} instruction \b Disallow start maximized mode diff --git a/Source/BinInterop.cpp b/Source/BinInterop.cpp index d50ae9b0..9ee28e41 100644 --- a/Source/BinInterop.cpp +++ b/Source/BinInterop.cpp @@ -334,7 +334,7 @@ static bool GetTLBVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low } #endif //~ !_WIN32 -bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low) +bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low, bool NotUsed) { bool found = false; #if defined(_WIN32) && !defined(NSIS_GETTLBVERSION_FORCEINTERNAL) @@ -345,11 +345,11 @@ bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low) return found; } -static bool GetDLLVersionUsingRE(const TCHAR *filepath, DWORD &high, DWORD &low) +static bool GetDLLVersionUsingRE(const TCHAR *filepath, DWORD &high, DWORD &low, bool Product) { bool found = false; LANGID anylangid = CResourceEditor::ANYLANGID; - unsigned long fileSize; + unsigned long fileSize, fieldofs = Product ? 2 : 0; void*pFileData = alloc_and_read_file(filepath, fileSize); if (!pFileData) return false; try @@ -369,7 +369,7 @@ static bool GetDLLVersionUsingRE(const TCHAR *filepath, DWORD &high, DWORD &low) VS_FIXEDFILEINFO *verinfo = (VS_FIXEDFILEINFO*)(resdata + len); if (ressize >= len + sizeof(VS_FIXEDFILEINFO) && verinfo->dwSignature == FIX_ENDIAN_INT32(VS_FFI_SIGNATURE)) { - high = FIX_ENDIAN_INT32(verinfo->dwFileVersionMS), low = FIX_ENDIAN_INT32(verinfo->dwFileVersionLS); + high = FIX_ENDIAN_INT32((&verinfo->dwFileVersionMS)[fieldofs]), low = FIX_ENDIAN_INT32((&verinfo->dwFileVersionLS)[fieldofs]); found = true; } } @@ -383,11 +383,11 @@ static bool GetDLLVersionUsingRE(const TCHAR *filepath, DWORD &high, DWORD &low) return found; } -static bool GetDLLVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low) +static bool GetDLLVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low, bool Product) { bool found = false; #ifdef _WIN32 - TCHAR path[1024], *name; + TCHAR path[1024], *name, fieldofs = Product ? 2 : 0; path[0] = 0; GetFullPathName(filepath, 1024, path, &name); @@ -401,7 +401,7 @@ static bool GetDLLVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low VS_FIXEDFILEINFO *pvsf; if (GetFileVersionInfo(path, 0, verSize, buf) && VerQueryValue(buf, _T("\\"), (void**) &pvsf, &valSize)) { - high = pvsf->dwFileVersionMS, low = pvsf->dwFileVersionLS; + high = (&pvsf->dwFileVersionMS)[fieldofs], low = (&pvsf->dwFileVersionLS)[fieldofs]; found = true; } free(buf); @@ -420,11 +420,11 @@ typedef struct tagMINI_IMAGE_VXD_HEADER { } MINI_IMAGE_VXD_HEADER, *PMINI_IMAGE_VXD_HEADER; #pragma pack(pop) -static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD &high, DWORD &low) +static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD &high, DWORD &low, bool Product) { bool found = false; FILEVIEW map; - char *filedata = create_file_view_readonly(filepath, map); + char *filedata = create_file_view_readonly(filepath, map), fieldofs = Product ? 2 : 0; if (filedata) { PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER) filedata; @@ -452,7 +452,7 @@ static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD &high, DWORD &low) VS_FIXEDFILEINFO *pFFI = MKPTR(VS_FIXEDFILEINFO*, pVSVI, 2 + 2 + 16); if (LE2HE32(pFFI->dwSignature) == 0xFEEF04BD) { - high = LE2HE32(pFFI->dwFileVersionMS), low = LE2HE32(pFFI->dwFileVersionLS); + high = LE2HE32((&pFFI->dwFileVersionMS)[fieldofs]), low = LE2HE32((&pFFI->dwFileVersionLS)[fieldofs]); found = true; } } @@ -465,11 +465,11 @@ static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD &high, DWORD &low) return found; } -bool GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low) +bool GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low, bool Product) { - bool result = GetDLLVersionUsingAPI(filepath, high, low); - if (!result) result = GetDLLVersionUsingRE(filepath, high, low); - if (!result) result = GetDLLVersionFromVXD(filepath, high, low); + bool result = GetDLLVersionUsingAPI(filepath, high, low, Product); + if (!result) result = GetDLLVersionUsingRE(filepath, high, low, Product); + if (!result) result = GetDLLVersionFromVXD(filepath, high, low, Product); return result; } diff --git a/Source/BinInterop.h b/Source/BinInterop.h index e135d941..d6e75ef1 100644 --- a/Source/BinInterop.h +++ b/Source/BinInterop.h @@ -26,9 +26,9 @@ signed char GetExeType(const void*pData, size_t Size); signed char GetExeType(const TCHAR*filepath); FILE* MSTLB_fopen(const TCHAR*filepath, size_t*pResId = 0); -bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low); +bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low, bool NotUsed = false); -bool GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low); +bool GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low, bool Product = false); typedef struct GENERICIMAGEINFO { UINT32 Width, Height; diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 4b48da74..a0b2a339 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -987,8 +987,8 @@ static int NSISCALL ExecuteEntry(entry *entry_) if ( ((BOOL(WINAPI*)(LPCTSTR,DWORD,DWORD,LPVOID))gfvi)(buf1,0,s1,b1) && ((BOOL(WINAPI*)(LPCVOID,LPCTSTR,LPVOID*,UINT*))vqv)(b1,_T("\\"),(void*)&pvsf1,&uLen) ) { - myitoa(highout,pvsf1->dwFileVersionMS); - myitoa(lowout,pvsf1->dwFileVersionLS); + myitoa(highout,(&pvsf1->dwFileVersionMS)[parm3]); + myitoa(lowout,(&pvsf1->dwFileVersionLS)[parm3]); exec_error--; } diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 012fd9dc..a1474ad0 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -130,7 +130,7 @@ enum #endif #ifdef NSIS_SUPPORT_GETDLLVERSION - EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout] + EW_GETDLLVERSION, // GetDLLVersion: 4 [file highout lowout fixedoffset] #endif #ifdef NSIS_SUPPORT_ACTIVEXREG diff --git a/Source/script.cpp b/Source/script.cpp index 004069a7..c36fc75e 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -4022,8 +4022,9 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) case TOK_GETDLLVERSIONLOCAL: { const TCHAR*cmdname=_T("GetDLLVersionLocal"); - DWORD low, high; - if (!GetDLLVersion(line.gettoken_str(1),high,low)) + DWORD low, high, prod = line.gettoken_enum(1, _T("/ProductVersion\0")) == 0 ? 2 : 0; + if (prod) line.eattoken(); + if (!GetDLLVersion(line.gettoken_str(1),high,low,!!prod)) { ERROR_MSG(_T("%") NPRIs _T(": error reading version info from \"%") NPRIs _T("\"\n"),cmdname,line.gettoken_str(1)); return PS_ERROR; @@ -4190,7 +4191,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) return add_entry(&ent); case TOK_GETWINVER: { - int k = line.gettoken_enum(2, _T("major\0minor\0build\0servicepack\0product\0ntddimajmin")), cb = 0, ofs = 0; + int k = line.gettoken_enum(2, _T("major\0minor\0build\0servicepack\0product\0ntddimajmin\0")), cb = 0, ofs = 0; switch(k) { case 0: cb = 1, ofs = ABI_OSINFOOFFSET + FIELD_OFFSET(osinfo, WVMaj); break; @@ -4235,6 +4236,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) case TOK_GETDLLVERSION: #ifdef NSIS_SUPPORT_GETDLLVERSION ent.which=EW_GETDLLVERSION; + if ((ent.offsets[3]=line.gettoken_enum(1, _T("/ProductVersion\0")) == 0 ? 2 : 0)) line.eattoken(); ent.offsets[0]=GetUserVarIndex(line, 2); ent.offsets[1]=GetUserVarIndex(line, 3); ent.offsets[2]=add_string(line.gettoken_str(1)); diff --git a/Source/scriptpp.cpp b/Source/scriptpp.cpp index 48eea839..f14b3ad2 100644 --- a/Source/scriptpp.cpp +++ b/Source/scriptpp.cpp @@ -607,17 +607,19 @@ int CEXEBuild::pp_getversion(int which_token, LineParser&line) { const bool tlb = TOK_P_GETTLBVERSION == which_token; const TCHAR *cmdname = tlb ? _T("!gettlbversion") : _T("!getdllversion"), *path; - DWORD ti = 1, flags = tlb ? PPGVHF_TLB : 0, low, high; + DWORD ti = 1, flags = tlb ? PPGVHF_TLB : 0, low, high, prod = 0; for (;; ++ti) { if (!_tcsicmp(line.gettoken_str(ti), _T("/noerrors"))) flags |= PPGVHF_NOERRORS; else if (!_tcsicmp(line.gettoken_str(ti), _T("/packed"))) flags |= PPGVHF_PACKED; + else if (!_tcsicmp(line.gettoken_str(ti), _T("/productversion"))) + ++prod; else break; } - if ((tlb ? GetTLBVersion : GetDLLVersion)(path = line.gettoken_str(ti), high, low)) flags |= PPGVHF_VALID; + if ((tlb ? GetTLBVersion : GetDLLVersion)(path = line.gettoken_str(ti), high, low, !!prod)) flags |= PPGVHF_VALID; return pp_getversionhelper(cmdname, path, line.gettoken_str(ti+1), high, low, flags); } diff --git a/Source/tokens.cpp b/Source/tokens.cpp index a20fd41d..ff42c9ec 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -50,8 +50,8 @@ static tokenType tokenlist[TOK__LAST] = {TOK_CHANGEUI,_T("ChangeUI"),2,0,_T("(all|dlg_id) ui_file.exe"),TP_GLOBAL}, {TOK_CLEARERRORS,_T("ClearErrors"),0,0,_T(""),TP_CODE}, {TOK_COMPTEXT,_T("ComponentText"),0,3,_T("[component_page_description] [component_subtext1] [component_subtext2]"),TP_PG}, -{TOK_GETDLLVERSION,_T("GetDLLVersion"),3,0,_T("filename $(user_var: high output) $(user_var: low output)"),TP_CODE}, -{TOK_GETDLLVERSIONLOCAL,_T("GetDLLVersionLocal"),3,0,_T("localfilename $(user_var: high output) $(user_var: low output)"),TP_CODE}, +{TOK_GETDLLVERSION,_T("GetDLLVersion"),3,1,_T("[/ProductVersion] filename $(user_var: high output) $(user_var: low output)"),TP_CODE}, +{TOK_GETDLLVERSIONLOCAL,_T("GetDLLVersionLocal"),3,1,_T("localfilename $(user_var: high output) $(user_var: low output)"),TP_CODE}, {TOK_GETFILETIME,_T("GetFileTime"),3,0,_T("file $(user_var: high output) $(user_var: low output)"),TP_CODE}, {TOK_GETFILETIMELOCAL,_T("GetFileTimeLocal"),3,0,_T("localfile $(user_var: high output) $(user_var: low output)"),TP_CODE}, {TOK_COPYFILES,_T("CopyFiles"),2,3,_T("[/SILENT] [/FILESONLY] source_path destination_path [total_size_in_kb]"),TP_CODE}, @@ -306,7 +306,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_P_TEMPFILE,_T("!tempfile"),1,0,_T("symbol"),TP_ALL}, {TOK_P_DELFILE,_T("!delfile"),1,1,_T("[/nonfatal] file"),TP_ALL}, {TOK_P_APPENDFILE,_T("!appendfile"),2,2,_T("[/CHARSET=<") TSTR_OUTPUTCHARSET _T(">] [/RAWNL] file appended_line"),TP_ALL}, -{TOK_P_GETDLLVERSION,_T("!getdllversion"),2,2,_T("[/noerrors] [/packed] localfilename define_basename"),TP_ALL}, +{TOK_P_GETDLLVERSION,_T("!getdllversion"),2,3,_T("[/noerrors] [/packed] [/productversion] localfilename define_basename"),TP_ALL}, {TOK_P_GETTLBVERSION,_T("!gettlbversion"),2,2,_T("[/noerrors] [/packed] localfilename define_basename"),TP_ALL}, {TOK_P_SEARCHPARSESTRING,_T("!searchparse"),3,-1,_T("[/ignorecase] [/noerrors] [/file] source_string_or_file substring OUTPUTSYM1 [substring [OUTPUTSYM2 [substring ...]]]"),TP_ALL},