Refactored GetDLLVersion
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6916 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
8e4b1c8e5f
commit
1ae118af99
9 changed files with 276 additions and 372 deletions
|
@ -48,55 +48,12 @@ FILE* MSTLB_fopen(const TCHAR*filepath, size_t*pResId)
|
||||||
|
|
||||||
#if !defined(_WIN32) || defined(NSIS_GETTLBVERSION_FORCEINTERNAL)
|
#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
|
#if 0
|
||||||
// midl /DOLDTLB=1 /oldtlb /tlb SLTG.tlb test.idl && midl /DNEWTLB=1 /newtlb /tlb MSFT.tlb test.idl
|
// midl /DOLDTLB=1 /oldtlb /tlb SLTG.tlb test.idl && midl /DNEWTLB=1 /newtlb /tlb MSFT.tlb test.idl
|
||||||
#ifdef NEWTLB
|
#ifdef NEWTLB
|
||||||
import "unknwn.idl";
|
import "unknwn.idl";
|
||||||
[
|
[ object, uuid(42424242-1111-1111-0001-424242424242) ] interface IInTeRfAcE1 : IUnknown { HRESULT I1_MeThOd1(); };
|
||||||
object, uuid(42424242-1111-1111-0001-424242424242),
|
[ object, uuid(42424242-1111-1111-0002-424242424242) ] interface IInTeRfAcE2 : IUnknown { [idempotent] HRESULT I2_MeThOd1(); };
|
||||||
//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(); };
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[ //msdn.microsoft.com/en-us/library/windows/desktop/aa367069
|
[ //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))
|
if (cbData >= sizeof(MSTLB_MSFT_MINIHEADER))
|
||||||
{
|
{
|
||||||
const MSTLB_MSFT_MINIHEADER &h = *(MSTLB_MSFT_MINIHEADER*) pData;
|
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?
|
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);
|
size_t eofPtr = MKPTR(size_t, pData, cbData);
|
||||||
const MSTLB_SLTG_HEADER &h = *(MSTLB_SLTG_HEADER*) pData;
|
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));
|
MSTLB_SLTG_SD *pSD = MKPTR(MSTLB_SLTG_SD*, &h, sizeof(MSTLB_SLTG_HEADER));
|
||||||
UINT32 streamCount = FIX_ENDIAN_INT16(h.Count);
|
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");
|
const TCHAR* rt = _T("TYPELIB");
|
||||||
int rn = (int) resid, rl = CResourceEditor::ANYLANGID;
|
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);
|
BYTE *pResData = resid == invalid_res_id ? re.GetFirstResource(rt, cbData) : GetResource(re, rt, rn, rl, cbData);
|
||||||
if (pResData)
|
if (pResData)
|
||||||
{
|
{
|
||||||
|
@ -301,19 +258,19 @@ static bool GetTLBVersionInterop(const TCHAR *filepath, DWORD &high, DWORD &low)
|
||||||
size_t resid;
|
size_t resid;
|
||||||
FILE *f = MSTLB_fopen(filepath, &resid);
|
FILE *f = MSTLB_fopen(filepath, &resid);
|
||||||
bool result = false, resonly = invalid_res_id != 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 (f) fclose(f);
|
||||||
if (filedata)
|
if (pFileData)
|
||||||
{
|
{
|
||||||
if (!result && !resonly) result = MSTLB_GetVersion(filedata, size, high, low); // A raw TLB file?
|
if (!result && !resonly) result = MSTLB_GetVersion(pFileData, size, high, low); // A raw TLB file?
|
||||||
if (!result) result = GetTLBVersionUsingRE(filedata, size, resid, high, low); // A resource in a PE file?
|
if (!result) result = GetTLBVersionUsingRE(pFileData, 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?
|
// TODO: if (!result) result = GetTLBVersion16(pFileData, size, resid, high, low); // A resouce in a 16-bit executable?
|
||||||
free(filedata);
|
free(pFileData);
|
||||||
}
|
}
|
||||||
// Not supported: if (!result) result = GetTLBVersionFromMoniker(filepath, high, low);
|
// Not supported: if (!result) result = GetTLBVersionFromMoniker(filepath, high, low);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#else //! !_WIN32
|
#else // !_WIN32
|
||||||
static bool GetTLBVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low)
|
static bool GetTLBVersionUsingAPI(const TCHAR *filepath, DWORD &high, DWORD &low)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -355,3 +312,206 @@ bool GetTLBVersion(const TCHAR *filepath, DWORD &high, DWORD &low)
|
||||||
#endif //~ _WIN32
|
#endif //~ _WIN32
|
||||||
return found;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -25,4 +25,6 @@
|
||||||
FILE* MSTLB_fopen(const TCHAR*filepath, size_t*pResId = 0);
|
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 GetDLLVersion(const TCHAR *filepath, DWORD &high, DWORD &low);
|
||||||
|
|
||||||
#endif //~ NSIS_BININTEROP_H
|
#endif //~ NSIS_BININTEROP_H
|
||||||
|
|
|
@ -114,36 +114,16 @@ struct NSISException : public NSISExceptionInner
|
||||||
NSISException(const tstring& msg) : NSISExceptionInner(TtoCString(msg)) {}
|
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<unsigned char>& 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<char*>(&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)
|
void Plugins::GetExports(const tstring &pathToDll, bool pe64, bool displayInfo)
|
||||||
{
|
{
|
||||||
vector<unsigned char> dlldata;
|
|
||||||
PIMAGE_NT_HEADERS pNTHdrs;
|
PIMAGE_NT_HEADERS pNTHdrs;
|
||||||
|
unsigned long dllsize;
|
||||||
|
BYTE *dlldata = alloc_and_read_file(pathToDll.c_str(), dllsize);
|
||||||
|
MANAGE_WITH(dlldata, free);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
read_file(pathToDll, dlldata);
|
if (!dllsize) return ;
|
||||||
if (dlldata.empty()) return;
|
pNTHdrs = CResourceEditor::GetNTHeaders(&dlldata[0]); // This might throw
|
||||||
pNTHdrs = CResourceEditor::GetNTHeaders(&dlldata[0]);
|
|
||||||
} catch (std::runtime_error&) {
|
} catch (std::runtime_error&) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,9 +120,9 @@ PRESOURCE_DIRECTORY CResourceEditor::GetResourceDirectory(
|
||||||
// Construction/Destruction
|
// Construction/Destruction
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CResourceEditor::CResourceEditor(BYTE* pbPE, int iSize, bool bKeepData /*=true*/) {
|
CResourceEditor::CResourceEditor(void* pbPE, int iSize, bool bKeepData /*=true*/) {
|
||||||
// Copy the data pointer
|
// Copy the data pointer
|
||||||
m_pbPE = pbPE;
|
m_pbPE = (BYTE*) pbPE;
|
||||||
m_iSize = iSize;
|
m_iSize = iSize;
|
||||||
m_bKeepData = bKeepData;
|
m_bKeepData = bKeepData;
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ typedef struct RESOURCE_DIRECTORY {
|
||||||
|
|
||||||
class CResourceEditor {
|
class CResourceEditor {
|
||||||
public:
|
public:
|
||||||
CResourceEditor(BYTE* pbPE, int iSize, bool bKeepData = true);
|
CResourceEditor(void* pbPE, int iSize, bool bKeepData = true);
|
||||||
virtual ~CResourceEditor();
|
virtual ~CResourceEditor();
|
||||||
enum { ANYLANGID = 0xffff };
|
enum { ANYLANGID = 0xffff };
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "winchar.h"
|
#include "winchar.h"
|
||||||
#include "ResourceEditor.h"
|
#include "ResourceEditor.h"
|
||||||
#include "DialogTemplate.h"
|
#include "DialogTemplate.h"
|
||||||
|
#include "BinInterop.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "dirreader.h"
|
#include "dirreader.h"
|
||||||
#include <nsis-version.h>
|
#include <nsis-version.h>
|
||||||
|
|
|
@ -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)
|
int CEXEBuild::pp_getversionhelper(const TCHAR *cmdname, const TCHAR *path, const TCHAR *basesymname, DWORD high, DWORD low, DWORD flags)
|
||||||
{
|
{
|
||||||
TCHAR *symbuf = m_templinebuf;
|
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"));
|
FILE *pF = tlb ? MSTLB_fopen(path) : FOPEN(path, ("rb"));
|
||||||
if (pF) fclose(pF);
|
if (pF) fclose(pF);
|
||||||
bool vnum = pF && (flags & PPGVHF_VALID); // LibraryLocal users want to detect "file not found" vs "no version info"
|
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 (!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);
|
ERROR_MSG(_T("%") NPRIs _T(": error reading version info from \"%") NPRIs _T("\"\n"), cmdname, path);
|
||||||
return PS_ERROR;
|
return PS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
325
Source/util.cpp
325
Source/util.cpp
|
@ -75,6 +75,11 @@ size_t my_strncpy(TCHAR*Dest, const TCHAR*Src, size_t cchMax)
|
||||||
return cch;
|
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 0 if everything is OK
|
||||||
// Returns -1 if can't find the file
|
// Returns -1 if can't find the file
|
||||||
// Returns -2 if the file is an invalid bitmap
|
// Returns -2 if the file is an invalid bitmap
|
||||||
|
@ -604,8 +609,43 @@ FILE* my_fopen(const TCHAR *path, const char *mode)
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t my_strftime(TCHAR *s, size_t max, const TCHAR *fmt, const struct tm *tm) {
|
unsigned long get_file_size32(FILE *f)
|
||||||
return _tcsftime(s, max, fmt, tm);
|
{
|
||||||
|
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) {
|
tstring get_full_path(const tstring &path) {
|
||||||
|
@ -1200,287 +1240,6 @@ void FlushOutputAndResetPrintColor()
|
||||||
#endif
|
#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()
|
unsigned char Platform_SupportsUTF8Conversion()
|
||||||
{
|
{
|
||||||
static unsigned char cached = 0;
|
static unsigned char cached = 0;
|
||||||
|
|
|
@ -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
|
// 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);
|
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_full_path(const tstring& path);
|
||||||
tstring get_dir_name(const tstring& path);
|
tstring get_dir_name(const tstring& path);
|
||||||
tstring get_file_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);
|
TCHAR *my_convert(const TCHAR *path);
|
||||||
void my_convert_free(TCHAR *converted_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)
|
#define OPEN(a, b) my_open(a, b)
|
||||||
|
|
||||||
#else // _WIN32
|
#else // _WIN32
|
||||||
|
@ -275,6 +273,10 @@ int my_open(const TCHAR *pathname, int flags);
|
||||||
FILE* my_fopen(const TCHAR *path, const char *mode);
|
FILE* my_fopen(const TCHAR *path, const char *mode);
|
||||||
#define FOPEN(a, b) my_fopen((a), (b))
|
#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
|
// round a value up to be a multiple of 512
|
||||||
// assumption: T is an int type
|
// assumption: T is an int type
|
||||||
template <class T> inline T align_to_512(const T x) { return (x+511) & ~511; }
|
template <class T> inline T align_to_512(const T x) { return (x+511) & ~511; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue