From 1ae118af991cf52c174901b231c31fdcb2f2171c Mon Sep 17 00:00:00 2001 From: anders_k Date: Wed, 4 Oct 2017 23:40:45 +0000 Subject: [PATCH] Refactored GetDLLVersion git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6916 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/BinInterop.cpp | 270 ++++++++++++++++++++++++------- Source/BinInterop.h | 2 + Source/Plugins.cpp | 32 +--- Source/ResourceEditor.cpp | 4 +- Source/ResourceEditor.h | 2 +- Source/script.cpp | 1 + Source/scriptpp.cpp | 4 +- Source/util.cpp | 325 +++++--------------------------------- Source/util.h | 8 +- 9 files changed, 276 insertions(+), 372 deletions(-) diff --git a/Source/BinInterop.cpp b/Source/BinInterop.cpp index f5aade0b..f5afbe86 100644 --- a/Source/BinInterop.cpp +++ b/Source/BinInterop.cpp @@ -48,55 +48,12 @@ FILE* MSTLB_fopen(const TCHAR*filepath, size_t*pResId) #if !defined(_WIN32) || defined(NSIS_GETTLBVERSION_FORCEINTERNAL) -unsigned long get_file_size32(FILE*f) -{ - unsigned long error = ~(0UL), result = error, restoreseek = false; - long cb; - fpos_t orgpos; - if (restoreseek ? 0 == fgetpos(f, &orgpos) : true) - if (0 == fseek(f, 0, SEEK_END)) - if ((cb = ftell(f)) != -1L) - if (restoreseek ? 0 == fsetpos(f, &orgpos) : true) - result = cb; - return result; -} - -void* alloc_and_read_file(FILE*f, unsigned long&size) -{ - void *result = 0, *mem = 0; - if (!f) return result; - size = get_file_size32(f); - mem = (~(0UL) != size) ? malloc(size) : 0; - if (mem) - if (0 == fseek(f, 0, SEEK_SET)) - if (fread(mem, 1, size, f) == size) - result = mem, mem = 0; - free(mem); - return result; -} - -/*void* alloc_and_read_file(const TCHAR*filepath, unsigned long&size) -{ - void *result = 0; - FILE*f = FOPEN(filepath, ("rb")); - if (f) - result = alloc_and_read_file(f, size), fclose(f); - return result; -}*/ - #if 0 // midl /DOLDTLB=1 /oldtlb /tlb SLTG.tlb test.idl && midl /DNEWTLB=1 /newtlb /tlb MSFT.tlb test.idl #ifdef NEWTLB import "unknwn.idl"; -[ - object, uuid(42424242-1111-1111-0001-424242424242), - //oleautomation, //TYPEFLAG_FOLEAUTOMATION? - //dual, //"Specifying dual on an interface implies that the interface is compatible with Automation, and therefore causes both the TYPEFLAG_FDUAL and TYPEFLAG_FOLEAUTOMATION flags to be set" -] -interface IInTeRfAcE1 : IUnknown { HRESULT I1_MeThOd1(); }; - -[ object, uuid(42424242-1111-1111-0002-424242424242) ] -interface IInTeRfAcE2 : IUnknown { [idempotent] HRESULT I2_MeThOd1(); }; +[ object, uuid(42424242-1111-1111-0001-424242424242) ] interface IInTeRfAcE1 : IUnknown { HRESULT I1_MeThOd1(); }; +[ object, uuid(42424242-1111-1111-0002-424242424242) ] interface IInTeRfAcE2 : IUnknown { [idempotent] HRESULT I2_MeThOd1(); }; #endif [ //msdn.microsoft.com/en-us/library/windows/desktop/aa367069 @@ -186,7 +143,7 @@ static bool MSTLB_GetVersion_MSFT(const void*pData, size_t cbData, DWORD &high, if (cbData >= sizeof(MSTLB_MSFT_MINIHEADER)) { const MSTLB_MSFT_MINIHEADER &h = *(MSTLB_MSFT_MINIHEADER*) pData; - if (FIX_ENDIAN_INT32(h.Sig) == 0x5446534D) + if (h.Sig == FIX_ENDIAN_INT32(0x5446534D)) { if (FIX_ENDIAN_INT16(h.FmtVerMaj) == 2 && FIX_ENDIAN_INT16(h.FmtVerMin) == 1) // Is this always 2.1? { @@ -223,7 +180,7 @@ static bool MSTLB_GetVersion_SLTG(const void*pData, size_t cbData, DWORD &high, { size_t eofPtr = MKPTR(size_t, pData, cbData); const MSTLB_SLTG_HEADER &h = *(MSTLB_SLTG_HEADER*) pData; - if (FIX_ENDIAN_INT32(h.Sig) == 0x047544C53 && MSTLB_IsSerializedOleGuid(h.Guid, 0x00020400, 0xffffff00)) // 0x000204xx for IID_ITypeLib and friends + if (h.Sig == FIX_ENDIAN_INT32(0x047544C53) && MSTLB_IsSerializedOleGuid(h.Guid, 0x00020400, 0xffffff00)) // 0x000204xx for IID_ITypeLib and friends { MSTLB_SLTG_SD *pSD = MKPTR(MSTLB_SLTG_SD*, &h, sizeof(MSTLB_SLTG_HEADER)); UINT32 streamCount = FIX_ENDIAN_INT16(h.Count); @@ -281,7 +238,7 @@ static bool GetTLBVersionUsingRE(const void*pPEFile, size_t cbData, size_t resid { const TCHAR* rt = _T("TYPELIB"); int rn = (int) resid, rl = CResourceEditor::ANYLANGID; - CResourceEditor re((BYTE*) pPEFile, (int) cbData); + CResourceEditor re((void*) pPEFile, (int) cbData); BYTE *pResData = resid == invalid_res_id ? re.GetFirstResource(rt, cbData) : GetResource(re, rt, rn, rl, cbData); if (pResData) { @@ -301,19 +258,19 @@ static bool GetTLBVersionInterop(const TCHAR *filepath, DWORD &high, DWORD &low) size_t resid; FILE *f = MSTLB_fopen(filepath, &resid); bool result = false, resonly = invalid_res_id != resid; - void *filedata = alloc_and_read_file(f, size); + void *pFileData = alloc_and_read_file(f, size); if (f) fclose(f); - if (filedata) + if (pFileData) { - if (!result && !resonly) result = MSTLB_GetVersion(filedata, size, high, low); // A raw TLB file? - if (!result) result = GetTLBVersionUsingRE(filedata, size, resid, high, low); // A resource in a PE file? - // TODO: if (!result) result = GetTLBVersion16(filedata, size, resid, high, low); // A resouce in a 16-bit executable? - free(filedata); + if (!result && !resonly) result = MSTLB_GetVersion(pFileData, size, high, low); // A raw TLB file? + if (!result) result = GetTLBVersionUsingRE(pFileData, size, resid, high, low); // A resource in a PE file? + // TODO: if (!result) result = GetTLBVersion16(pFileData, size, resid, high, low); // A resouce in a 16-bit executable? + free(pFileData); } // Not supported: if (!result) result = GetTLBVersionFromMoniker(filepath, high, low); return result; } -#else //! !_WIN32 +#else // !_WIN32 static bool GetTLBVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low) { bool found = false; @@ -355,3 +312,206 @@ bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low) #endif //~ _WIN32 return found; } + +static bool GetDLLVersionUsingRE(const TCHAR *filepath, DWORD &high, DWORD &low) +{ + bool found = false; + LANGID anylangid = CResourceEditor::ANYLANGID; + unsigned long fileSize; + void*pFileData = alloc_and_read_file(filepath, fileSize); + if (!pFileData) return false; + try + { + CResourceEditor re(pFileData, fileSize); + LPBYTE resdata = re.GetResource(VS_FILE_INFO, VS_VERSION_INFO, anylangid); + if (resdata) + { + size_t ressize = re.GetResourceSize(VS_FILE_INFO, VS_VERSION_INFO, anylangid); + size_t vsvhdrsize = sizeof(WORD) * 3; + if (ressize > vsvhdrsize) + { + // Locate VS_FIXEDFILEINFO inside VS_VERSIONINFO + WINWCHAR *szKey = (WINWCHAR*)(resdata + vsvhdrsize); + size_t len = vsvhdrsize + (WinWStrLen(szKey) + 1) * sizeof(WINWCHAR); + len = (len + 3) & ~3; // Align on DWORD boundary + 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); + found = true; + } + } + re.FreeResource(resdata); + } + } + catch (std::exception&) + { + } + free(pFileData); + return found; +} + +static bool GetDLLVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low) +{ + bool found = false; +#ifdef _WIN32 + TCHAR path[1024], *name; + path[0] = 0; + GetFullPathName(filepath, 1024, path, &name); + + DWORD ignore, verSize = GetFileVersionInfoSize(path, &ignore); + if (verSize) + { + void *buf = malloc(verSize); + if (buf) + { + UINT valSize; + VS_FIXEDFILEINFO *pvsf; + if (GetFileVersionInfo(path, 0, verSize, buf) && VerQueryValue(buf, _T("\\"), (void**) &pvsf, &valSize)) + { + high = pvsf->dwFileVersionMS, low = pvsf->dwFileVersionLS; + found = true; + } + free(buf); + } + } +#endif + return found; +} + +#pragma pack(push, pre_vxd_ver, 1) +typedef struct _VXD_VERSION_RESOURCE { + char cType; + WORD wID; + char cName; + WORD wOrdinal; + WORD wFlags; + DWORD dwResSize; + BYTE bVerData; +} VXD_VERSION_RESOURCE, *PVXD_VERSION_RESOURCE; +#pragma pack(pop, pre_vxd_ver) + +#ifdef _WIN32 +static void* CreateReadOnlyFullMappedView(LPCTSTR szFile, DWORD Access, DWORD Share, DWORD Mode) +{ + void *pView = NULL; + HANDLE hFile = CreateFile(szFile, Access, Share, NULL, Mode, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) return pView; + HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMap != INVALID_HANDLE_VALUE) + { + CloseHandle(hFile); + if ((pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0))) + { + CloseHandle(hMap); + } + else + { + DWORD error = GetLastError(); + CloseHandle(hMap); + SetLastError(error); + } + } + else + { + DWORD error = GetLastError(); + CloseHandle(hFile); + SetLastError(error); + } + return pView; +} + +static BOOL GetVxdVersion(LPCTSTR szFile, LPDWORD lpdwLen, LPVOID lpData) +{ + BOOL result = FALSE; + DWORD resSize = 0, outSize = *lpdwLen; + void *pView = CreateReadOnlyFullMappedView(szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING); + if (!pView) return FALSE; + + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER) pView; + if (pDosHdr->e_magic == IMAGE_DOS_SIGNATURE) + { + PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS) ((ULONG_PTR) pView + pDosHdr->e_lfanew); + if ((DWORD) pNtHdr->Signature == IMAGE_VXD_SIGNATURE) // Is it a little-endian VXD? + { + PIMAGE_VXD_HEADER pLEHdr = (PIMAGE_VXD_HEADER) pNtHdr; + if (pLEHdr->e32_winreslen != 0) + { + PVXD_VERSION_RESOURCE pVerRes; + pVerRes = (VXD_VERSION_RESOURCE*) ((ULONG_PTR) pView + pLEHdr->e32_winresoff); + resSize = pVerRes->dwResSize; + if (lpData && outSize >= resSize) + { + void *pResData = &(pVerRes->bVerData); + ZeroMemory(lpData, outSize); + CopyMemory(lpData, pResData, resSize); + result = TRUE; + } + else + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + else + SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); + } + else + SetLastError(ERROR_BAD_FORMAT); + } + else + SetLastError(ERROR_BAD_FORMAT); + + UnmapViewOfFile(pView); + *lpdwLen = resSize; + return result; +} + +static DWORD GetVxdVersionInfoSize(LPCTSTR szFile) +{ + DWORD result = 0; + if (!GetVxdVersion(szFile, &result, NULL)) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) // Successfully queried the required size? + { + SetLastError(0); + return result; + } + } + return result; +} + +static BOOL GetVxdVersionInfo(LPCTSTR szFile, DWORD dwLen, LPVOID lpData) +{ + return GetVxdVersion(szFile, &dwLen, lpData); +} +#endif //_WIN32 + +static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD &high, DWORD &low) +{ + bool found = false; +#ifdef _WIN32 + DWORD verSize = GetVxdVersionInfoSize(filepath); + if (verSize) + { + void *buf = malloc(verSize); + if (buf) + { + UINT valSize; + VS_FIXEDFILEINFO *pvsf; + if (GetVxdVersionInfo(filepath, verSize, buf) && VerQueryValue(buf, _T("\\"), (void**) &pvsf, &valSize)) + { + high = pvsf->dwFileVersionMS, low = pvsf->dwFileVersionLS; + found = true; + } + free(buf); + } + } +#endif + return found; +} + +bool GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low) +{ + bool result = GetDLLVersionUsingAPI(filepath, high, low); + if (!result) result = GetDLLVersionUsingRE(filepath, high, low); + if (!result) result = GetDLLVersionFromVXD(filepath, high, low); + return result; +} diff --git a/Source/BinInterop.h b/Source/BinInterop.h index de064518..af16d6e5 100644 --- a/Source/BinInterop.h +++ b/Source/BinInterop.h @@ -25,4 +25,6 @@ FILE* MSTLB_fopen(const TCHAR*filepath, size_t*pResId = 0); bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low); +bool GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low); + #endif //~ NSIS_BININTEROP_H diff --git a/Source/Plugins.cpp b/Source/Plugins.cpp index e8bd86d0..ac202aa1 100644 --- a/Source/Plugins.cpp +++ b/Source/Plugins.cpp @@ -114,36 +114,16 @@ struct NSISException : public NSISExceptionInner NSISException(const tstring& msg) : NSISExceptionInner(TtoCString(msg)) {} }; -namespace { -// This function slurps the whole file into the vector. -// Modified so the huge vector isn't returned by value. -void read_file(const tstring& filename, vector& data) -{ - FILE*file = FOPEN(filename.c_str(), ("rb")); - if (!file) throw NSISException(_T("Can't open file '") + filename + _T("'")); - MANAGE_WITH(file, fclose); - bool succ = false; - - if (!fseek(file, 0, SEEK_END)) - { - const long filesize = ftell(file); - rewind(file); - data.resize(filesize); - size_t cbio = fread(reinterpret_cast(&data[0]), 1, filesize, file); - succ = cbio == (size_t)filesize; - } - if (!succ) throw NSISException(_T("Couldn't read entire file '") + filename + _T("'")); -} -} - void Plugins::GetExports(const tstring &pathToDll, bool pe64, bool displayInfo) { - vector dlldata; PIMAGE_NT_HEADERS pNTHdrs; + unsigned long dllsize; + BYTE *dlldata = alloc_and_read_file(pathToDll.c_str(), dllsize); + MANAGE_WITH(dlldata, free); + try { - read_file(pathToDll, dlldata); - if (dlldata.empty()) return; - pNTHdrs = CResourceEditor::GetNTHeaders(&dlldata[0]); + if (!dllsize) return ; + pNTHdrs = CResourceEditor::GetNTHeaders(&dlldata[0]); // This might throw } catch (std::runtime_error&) { return; } diff --git a/Source/ResourceEditor.cpp b/Source/ResourceEditor.cpp index b34ece63..1f0cd14a 100644 --- a/Source/ResourceEditor.cpp +++ b/Source/ResourceEditor.cpp @@ -120,9 +120,9 @@ PRESOURCE_DIRECTORY CResourceEditor::GetResourceDirectory( // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CResourceEditor::CResourceEditor(BYTE* pbPE, int iSize, bool bKeepData /*=true*/) { +CResourceEditor::CResourceEditor(void* pbPE, int iSize, bool bKeepData /*=true*/) { // Copy the data pointer - m_pbPE = pbPE; + m_pbPE = (BYTE*) pbPE; m_iSize = iSize; m_bKeepData = bKeepData; diff --git a/Source/ResourceEditor.h b/Source/ResourceEditor.h index 4afaf0d9..c85bbeca 100644 --- a/Source/ResourceEditor.h +++ b/Source/ResourceEditor.h @@ -119,7 +119,7 @@ typedef struct RESOURCE_DIRECTORY { class CResourceEditor { public: - CResourceEditor(BYTE* pbPE, int iSize, bool bKeepData = true); + CResourceEditor(void* pbPE, int iSize, bool bKeepData = true); virtual ~CResourceEditor(); enum { ANYLANGID = 0xffff }; diff --git a/Source/script.cpp b/Source/script.cpp index febcad9e..6715db3d 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -23,6 +23,7 @@ #include "winchar.h" #include "ResourceEditor.h" #include "DialogTemplate.h" +#include "BinInterop.h" #include "lang.h" #include "dirreader.h" #include diff --git a/Source/scriptpp.cpp b/Source/scriptpp.cpp index c6d36374..422f8227 100644 --- a/Source/scriptpp.cpp +++ b/Source/scriptpp.cpp @@ -584,7 +584,7 @@ enum { PPGVHF_VALID = 0x01, PPGVHF_NOERRORS = 0x02, PPGVHF_PACKED = 0x04, PPGVHF int CEXEBuild::pp_getversionhelper(const TCHAR *cmdname, const TCHAR *path, const TCHAR *basesymname, DWORD high, DWORD low, DWORD flags) { TCHAR *symbuf = m_templinebuf; - DWORD tlb = (flags & PPGVHF_TLB); + DWORD tlb = (flags & PPGVHF_TLB), noerrors = (flags & PPGVHF_NOERRORS); 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" @@ -594,7 +594,7 @@ int CEXEBuild::pp_getversionhelper(const TCHAR *cmdname, const TCHAR *path, cons if (!pF) { - if (flags & PPGVHF_NOERRORS) return PS_OK; + if (noerrors) return PS_OK; ERROR_MSG(_T("%") NPRIs _T(": error reading version info from \"%") NPRIs _T("\"\n"), cmdname, path); return PS_ERROR; } diff --git a/Source/util.cpp b/Source/util.cpp index f205a385..1909f21e 100644 --- a/Source/util.cpp +++ b/Source/util.cpp @@ -75,6 +75,11 @@ size_t my_strncpy(TCHAR*Dest, const TCHAR*Src, size_t cchMax) return cch; } +size_t my_strftime(TCHAR *s, size_t max, const TCHAR *fmt, const struct tm *tm) +{ + return _tcsftime(s, max, fmt, tm); +} + // Returns 0 if everything is OK // Returns -1 if can't find the file // Returns -2 if the file is an invalid bitmap @@ -604,8 +609,43 @@ FILE* my_fopen(const TCHAR *path, const char *mode) return f; } -size_t my_strftime(TCHAR *s, size_t max, const TCHAR *fmt, const struct tm *tm) { - return _tcsftime(s, max, fmt, tm); +unsigned long get_file_size32(FILE *f) +{ + unsigned long error = ~(0UL), result = error; + long cb, restoreseek = true; + fpos_t orgpos; + if (restoreseek ? 0 == fgetpos(f, &orgpos) : true) + if (0 == fseek(f, 0, SEEK_END)) + if ((cb = ftell(f)) != -1L) + if (restoreseek ? 0 == fsetpos(f, &orgpos) : true) + result = cb; + return result; +} + +BYTE* alloc_and_read_file(FILE *f, unsigned long &size) +{ + BYTE *result = 0, *mem = 0; + if (!f) return result; + size = get_file_size32(f); + mem = (~(0UL) != size) ? (BYTE*) malloc(size) : 0; + if (mem) + if (0 == fseek(f, 0, SEEK_SET)) + if (fread(mem, 1, size, f) == size) + result = mem, mem = 0; + free(mem); + return result; +} + +BYTE* alloc_and_read_file(const TCHAR *filepath, unsigned long &size) +{ + BYTE *result = 0; + FILE*f = FOPEN(filepath, ("rb")); + if (f) + { + result = alloc_and_read_file(f, size); + fclose(f); + } + return result; } tstring get_full_path(const tstring &path) { @@ -1200,287 +1240,6 @@ void FlushOutputAndResetPrintColor() #endif } - -static bool GetDLLVersionUsingRE(const TCHAR *filepath, DWORD& high, DWORD & low) -{ - bool found = false; - LANGID anylangid = CResourceEditor::ANYLANGID; - - FILE *fdll = FOPEN(filepath, ("rb")); - if (!fdll) - return 0; - - fseek(fdll, 0, SEEK_END); - unsigned int len = ftell(fdll); - fseek(fdll, 0, SEEK_SET); - - LPBYTE dll = (LPBYTE) malloc(len); - - if (!dll) - { - fclose(fdll); - return 0; - } - - if (fread(dll, 1, len, fdll) != len) - { - fclose(fdll); - free(dll); - return 0; - } - fclose(fdll); - - try - { - CResourceEditor *dllre = new CResourceEditor(dll, len); - 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 (versize > sizeof(WORD) * 3) - { - // get VS_FIXEDFILEINFO from VS_VERSIONINFO - WINWCHAR *szKey = (WINWCHAR *)(ver + sizeof(WORD) * 3); - size_t len = (WinWStrLen(szKey) + 1) * sizeof(WINWCHAR) + sizeof(WORD) * 3; - len = (len + 3) & ~3; // align on DWORD boundary - VS_FIXEDFILEINFO *verinfo = (VS_FIXEDFILEINFO *)(ver + len); - if (versize > len && verinfo->dwSignature == VS_FFI_SIGNATURE) - { - found = true, low = verinfo->dwFileVersionLS, high = verinfo->dwFileVersionMS; - } - } - dllre->FreeResource(ver); - } - - delete dllre; - } - catch (exception&) - { - } - - return found; -} - -static bool GetDLLVersionUsingAPI(const TCHAR *filepath, DWORD& high, DWORD& low) -{ - bool found = false; - -#ifdef _WIN32 - TCHAR path[1024]; - TCHAR *name; - path[0] = 0; - - GetFullPathName(filepath, 1024, path, &name); - - DWORD d; - DWORD verSize = GetFileVersionInfoSize(path, &d); - if (verSize) - { - void *buf = (void *) GlobalAlloc(GPTR, verSize); - if (buf) - { - UINT uLen; - VS_FIXEDFILEINFO *pvsf; - if (GetFileVersionInfo(path, 0, verSize, buf) && VerQueryValue(buf, _T("\\"), (void**) &pvsf, &uLen)) - { - found = true, low = pvsf->dwFileVersionLS, high = pvsf->dwFileVersionMS; - } - GlobalFree(buf); - } - } -#endif - - return found; -} - -#ifdef _WIN32 - -// the following structure must be byte-aligned. -#pragma pack( push, pre_vxd_ver, 1 ) -typedef struct _VXD_VERSION_RESOURCE { - char cType; // Should not be converted to TCHAR (JP) - WORD wID; - char cName; // Should not be converted to TCHAR (JP) - WORD wOrdinal; - WORD wFlags; - DWORD dwResSize; - BYTE bVerData; -} VXD_VERSION_RESOURCE, *PVXD_VERSION_RESOURCE; -#pragma pack( pop, pre_vxd_ver ) - -static BOOL GetVxdVersion( LPCTSTR szFile, LPDWORD lpdwLen, LPVOID lpData ) -{ - - HANDLE hFile = NULL; - HANDLE hFileMapping = NULL; - void * pView = NULL; - DWORD dwSize = 0; - DWORD dwError = 0; - - PIMAGE_DOS_HEADER pDosExeHdr = NULL; - PIMAGE_NT_HEADERS pNtExeHdr = NULL; - PIMAGE_VXD_HEADER pLEHdr = NULL; - PVXD_VERSION_RESOURCE pVerRes = NULL; - LPVOID pRawRes = NULL; - - // Open the file for shared read access. - hFile = CreateFile( szFile, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, NULL ); - if ( hFile == INVALID_HANDLE_VALUE ) - { - return FALSE; - } - - // Create a read-only file mapping object for the file. - hFileMapping = CreateFileMapping( hFile, NULL, - PAGE_READONLY, 0, 0, NULL); - if ( !hFileMapping ) - { - dwError = GetLastError(); - if ( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile ); - SetLastError( dwError ); - return FALSE; - } - - // Map a view of the the file. - pView = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 ); - if ( !pView ) - { - dwError = GetLastError(); - if ( hFileMapping ) CloseHandle( hFileMapping ); - if ( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile ); - SetLastError( dwError ); - return FALSE; - } - - // The DOS header begins at byte 0. - pDosExeHdr = (PIMAGE_DOS_HEADER) pView; - - // Check to make sure the file has a DOS EXE header. - if ( pDosExeHdr->e_magic != IMAGE_DOS_SIGNATURE ) - { - if ( pView ) UnmapViewOfFile( pView ); - if ( hFileMapping ) CloseHandle( hFileMapping ); - if ( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile ); - SetLastError( ERROR_BAD_FORMAT ); - return FALSE; - } - - // Find the beginning of the NT header at offset e_lfanew. - pNtExeHdr = (PIMAGE_NT_HEADERS) ( (ULONG_PTR) pView + pDosExeHdr->e_lfanew ); - - // Check to make sure the file is a VxD. - if ( (DWORD) pNtExeHdr->Signature != IMAGE_VXD_SIGNATURE ) - { - if ( pView ) UnmapViewOfFile( pView ); - if ( hFileMapping ) CloseHandle( hFileMapping ); - if ( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile ); - SetLastError( ERROR_BAD_FORMAT ); - return FALSE; - } - - // The LE header begins at the same place as the NT header. - pLEHdr = (PIMAGE_VXD_HEADER) pNtExeHdr; - - // e32_winreslen contains the size of the VxD's version resource. - if ( pLEHdr->e32_winreslen == 0 ) { - *lpdwLen = 0; - if ( pView ) UnmapViewOfFile( pView ); - if ( hFileMapping ) CloseHandle( hFileMapping ); - if ( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile ); - SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND ); - return FALSE; - } - - // e32_winresoff contains the offset of the resource in the VxD. - pVerRes = (VXD_VERSION_RESOURCE *) ( (ULONG_PTR) pView + pLEHdr->e32_winresoff ); - dwSize = pVerRes->dwResSize; - pRawRes = &(pVerRes->bVerData); - - // Make sure the supplied buffer is large enough for the resource. - if ( ( lpData == NULL ) || ( *lpdwLen < dwSize ) ) { - *lpdwLen = dwSize; - if ( pView ) UnmapViewOfFile( pView ); - if ( hFileMapping ) CloseHandle( hFileMapping ); - if ( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile ); - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } - - // Zero the passed buffer and copy the resource into it. - ZeroMemory( lpData, *lpdwLen ); - CopyMemory( lpData, pRawRes, dwSize ); - *lpdwLen = dwSize; - - // Clean up resources. - if ( pView ) UnmapViewOfFile( pView ); - if ( hFileMapping ) CloseHandle( hFileMapping ); - if ( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile ); - SetLastError(0); // Why bother? - return TRUE; -} - -static DWORD GetVxdVersionInfoSize( LPCTSTR szFile ) -{ - DWORD dwResult = 0; - - // Call GetVxdVersion() with NULL for the pointer to the buffer. - if ( !GetVxdVersion( szFile, &dwResult, NULL ) ) - { - DWORD dwError = GetLastError(); - - // GetVxdVersion() will fail with ERROR_INSUFFICIENT_BUFFER and - // the required buffer size will be returned in dwResult. - if ( dwError == ERROR_INSUFFICIENT_BUFFER ) - { - SetLastError( 0 ); - return dwResult; - } - } - - // The following line is never executed. - return 0; -} - -static BOOL GetVxdVersionInfo( LPCTSTR szFile, DWORD dwLen, LPVOID lpData ) -{ - return GetVxdVersion( szFile, &dwLen, lpData ); -} - -#endif //_WIN32 - -static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD& high, DWORD& low) -{ - bool found = false; -#ifdef _WIN32 - DWORD verSize = GetVxdVersionInfoSize(filepath); - if (verSize) - { - void *buf = (void *) GlobalAlloc(GPTR, verSize); - if (buf) - { - UINT uLen; - VS_FIXEDFILEINFO *pvsf; - if (GetVxdVersionInfo(filepath, verSize, buf) && VerQueryValue(buf, _T("\\"), (void**) &pvsf, &uLen)) - { - found = true, low = pvsf->dwFileVersionLS, high = pvsf->dwFileVersionMS; - } - GlobalFree(buf); - } - } -#endif - return found; -} - -bool GetDLLVersion(const TCHAR *filepath, DWORD& high, DWORD& low) -{ - if (GetDLLVersionUsingAPI(filepath, high, low)) return true; - if (GetDLLVersionUsingRE(filepath, high, low)) return true; - if (GetDLLVersionFromVXD(filepath, high, low)) return true; - return false; -} - unsigned char Platform_SupportsUTF8Conversion() { static unsigned char cached = 0; diff --git a/Source/util.h b/Source/util.h index 3879e67b..ee6424eb 100644 --- a/Source/util.h +++ b/Source/util.h @@ -41,8 +41,6 @@ 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 TCHAR *filepath, DWORD &high, DWORD &low); - tstring get_full_path(const tstring& path); tstring get_dir_name(const tstring& path); tstring get_file_name(const tstring& path); @@ -259,8 +257,8 @@ int _wstat(const wchar_t *Path, struct stat *pS); TCHAR *my_convert(const TCHAR *path); void my_convert_free(TCHAR *converted_path); -int my_open(const TCHAR *pathname, int flags); +int my_open(const TCHAR *pathname, int flags); #define OPEN(a, b) my_open(a, b) #else // _WIN32 @@ -275,6 +273,10 @@ int my_open(const TCHAR *pathname, int flags); FILE* my_fopen(const TCHAR *path, const char *mode); #define FOPEN(a, b) my_fopen((a), (b)) +unsigned long get_file_size32(FILE *f); +BYTE* alloc_and_read_file(FILE *f, unsigned long &size); +BYTE* alloc_and_read_file(const TCHAR *filepath, unsigned long &size); + // round a value up to be a multiple of 512 // assumption: T is an int type template inline T align_to_512(const T x) { return (x+511) & ~511; }