From 38d7adce157f9e9020f6c7546ad3fcf7487f05c4 Mon Sep 17 00:00:00 2001 From: kichik Date: Sat, 11 Sep 2004 11:25:19 +0000 Subject: [PATCH] implemented GetDLLVersionLocal for non Win32 platforms git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3653 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/Platform.h | 10 ++++++ Source/ResourceEditor.cpp | 32 ++++++++++++++++-- Source/ResourceEditor.h | 1 + Source/script.cpp | 70 +++++++++++++++++++++++++++++++++++---- 4 files changed, 104 insertions(+), 9 deletions(-) diff --git a/Source/Platform.h b/Source/Platform.h index 52c1be82..1434e116 100644 --- a/Source/Platform.h +++ b/Source/Platform.h @@ -361,6 +361,16 @@ typedef WORD LANGID; # define RT_VERSION MAKEINTRESOURCE(16) #endif +#ifndef VS_FILE_INFO +# define VS_FILE_INFO RT_VERSION +#endif +#ifndef VS_VERSION_INFO +# define VS_VERSION_INFO 1 +#endif +#ifndef VS_FFI_SIGNATURE +# define VS_FFI_SIGNATURE 0xFEEFO4BD +#endif + // message box #ifndef MB_OK diff --git a/Source/ResourceEditor.cpp b/Source/ResourceEditor.cpp index 4cc417ff..f73cde42 100644 --- a/Source/ResourceEditor.cpp +++ b/Source/ResourceEditor.cpp @@ -188,8 +188,8 @@ bool CResourceEditor::UpdateResource(WORD szType, WORD szName, LANGID wLanguage, return UpdateResource(MAKEINTRESOURCE(szType), MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize); } -// Returns a copy of the resource requested -// Returns 0 if resource can't be found +// Returns a copy of the requested resource +// Returns 0 if the requested resource can't be found BYTE* CResourceEditor::GetResource(char* szType, char* szName, LANGID wLanguage) { CResourceDirectory* nameDir = 0; CResourceDirectory* langDir = 0; @@ -219,6 +219,34 @@ BYTE* CResourceEditor::GetResource(char* szType, char* szName, LANGID wLanguage) return NULL; } +// Returns the size of the requested resource +// Returns -1 if the requested resource can't be found +int CResourceEditor::GetResourceSize(char* szType, char* szName, LANGID wLanguage) { + CResourceDirectory* nameDir = 0; + CResourceDirectory* langDir = 0; + CResourceDataEntry* data = 0; + + int i = m_cResDir->Find(szType); + if (i > -1) { + nameDir = m_cResDir->GetEntry(i)->GetSubDirectory(); + i = nameDir->Find(szName); + if (i > -1) { + langDir = nameDir->GetEntry(i)->GetSubDirectory(); + i = 0; + if (wLanguage) + i = langDir->Find(wLanguage); + if (i > -1) { + data = langDir->GetEntry(i)->GetDataEntry(); + } + } + } + + if (data) + return (int) data->GetSize(); + else + return -1; +} + void CResourceEditor::FreeResource(BYTE* pbResource) { if (pbResource) diff --git a/Source/ResourceEditor.h b/Source/ResourceEditor.h index 20e3e02f..759bc6b7 100644 --- a/Source/ResourceEditor.h +++ b/Source/ResourceEditor.h @@ -104,6 +104,7 @@ public: bool UpdateResource(char* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); bool UpdateResource(WORD szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); BYTE* GetResource(char* szType, char* szName, LANGID wLanguage); + int GetResourceSize(char* szType, char* szName, LANGID wLanguage); void FreeResource(BYTE* pbResource); bool AddExtraVirtualSize2PESection(const char* pszSectionName, int addsize); diff --git a/Source/script.cpp b/Source/script.cpp index a8b485c4..2be66f21 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -3199,7 +3199,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) #else if (trim) { - ERROR_MSG("Error: BrandingText /TRIM* disabled for non Win32 platforms.\n"); + ERROR_MSG("Error: BrandingText /TRIM* is disabled for non Win32 platforms.\n"); return PS_ERROR; } #endif @@ -4338,11 +4338,11 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) return add_entry(&ent); case TOK_GETDLLVERSIONLOCAL: { -#ifdef _WIN32 char buf[128]; DWORD low=0, high=0; - DWORD s,d; int flag=0; +#ifdef _WIN32 + DWORD s,d; int alloced=0; char *path=line.gettoken_str(1); if (!((*path == '\\' && path[1] == '\\') || (*path && path[1] == ':'))) { @@ -4390,6 +4390,66 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } } if (alloced) free(path); +#else + FILE *fdll = FOPEN(line.gettoken_str(1), "rb"); + if (!fdll) { + ERROR_MSG("Error: Can't open \"%s\"!\n", line.gettoken_str(1)); + return PS_ERROR; + } + + fseek(fdll, 0, SEEK_END); + unsigned int len = ftell(fdll); + fseek(fdll, 0, SEEK_SET); + LPBYTE dll = (LPBYTE) malloc(len); + if (!dll) { + ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n", dll); + extern void quit(); quit(); + } + if (fread(dll, 1, len, fdll) != len) { + fclose(fdll); + free(dll); + ERROR_MSG("Error: Can't read \"%s\"!\n", line.gettoken_str(1)); + return PS_ERROR; + } + fclose(fdll); + + try + { + CResourceEditor *dllre = new CResourceEditor(dll, len); + LPBYTE ver = dllre->GetResource(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0); + int versize = dllre->GetResourceSize(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0); + + if (ver) + { + if (versize > sizeof(WORD) * 3) + { + // get VS_FIXEDFILEINFO from VS_VERSIONINFO + WCHAR *szKey = (WCHAR *)(ver + sizeof(WORD) * 3); + int len = WCStrLen(szKey) * sizeof(WCHAR) + sizeof(WORD) * 3; + len = (len + 3) & ~3; // align on DWORD boundry + VS_FIXEDFILEINFO *verinfo = (VS_FIXEDFILEINFO *)(ver + len); + if (versize > len && verinfo->dwSignature == VS_FFI_SIGNATURE) + { + low = verinfo->dwFileVersionLS; + high = verinfo->dwFileVersionMS; + flag = 1; + } + } + dllre->FreeResource(ver); + } + + delete dllre; + } + catch (exception& err) { + free(dll); + ERROR_MSG( + "GetDLLVersionLocal: error reading version info from \"%s\": %s\n", + line.gettoken_str(1), + err.what() + ); + return PS_ERROR; + } +#endif if (!flag) { ERROR_MSG("GetDLLVersionLocal: error reading version info from \"%s\"\n",line.gettoken_str(1)); @@ -4412,10 +4472,6 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) if (ent.offsets[0]<0) PRINTHELP() SCRIPT_MSG("GetDLLVersionLocal: %s (%u,%u)->(%s,%s)\n", line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3)); -#else - ERROR_MSG("Error: GetDLLVersionLocal is disabled for non Win32 platforms.\n"); - return PS_ERROR; -#endif } return add_entry(&ent); case TOK_GETFILETIMELOCAL: