Skip to content

Instantly share code, notes, and snippets.

@sredna
Last active October 16, 2017 19:57
Show Gist options
  • Select an option

  • Save sredna/585931b3f07813f8825a36b9d847719a to your computer and use it in GitHub Desktop.

Select an option

Save sredna/585931b3f07813f8825a36b9d847719a to your computer and use it in GitHub Desktop.
NSIS VXD version interop
#include <string.h> // strlen
#pragma pack(push, 1)
typedef struct tagMINI_IMAGE_VXD_HEADER {
WORD e32_magic, endian;
BYTE padding[180];
DWORD e32_winresoff, e32_winreslen;
WORD e32_devid, e32_ddkver;
} MINI_IMAGE_VXD_HEADER, *PMINI_IMAGE_VXD_HEADER;
#pragma pack(pop)
#define LE2HE16 FIX_ENDIAN_INT16
#define LE2HE32 FIX_ENDIAN_INT32
#define HE2LE16 LE2HE16
typedef struct {
#ifdef _WIN32
char*pView;
#else
TODO: If you don't need more than one member we can get rid of this entire struct because Windows only needs the view pointer
#endif
} NSIS_ROMAPPEDFILE;
#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;
}
#endif
void CloseMemMapFileView(NSIS_ROMAPPEDFILE&info)
{
#ifdef _WIN32
if (info.pView) UnmapViewOfFile(info.pView);
#else
TODO
#endif
}
char* CreateMemMapFileView(const TCHAR *filepath, NSIS_ROMAPPEDFILE&info)
{
char *view = 0;
#ifdef _WIN32
view = info.pView = (char*) CreateReadOnlyFullMappedView(filepath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING);
#else
TODO
#endif
return view;
}
static bool GetDLLVersionFromVXD(const TCHAR *filepath, DWORD &high, DWORD &low)
{
bool found = false;
NSIS_ROMAPPEDFILE map;
char *filedata = CreateMemMapFileView(filepath, map);
if (filedata)
{
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER) filedata;
if ((pDosHdr->e_magic == 0x5A4D) | (pDosHdr->e_magic == 0x4D5A))
{
PMINI_IMAGE_VXD_HEADER pVxdHdr = MKPTR(PMINI_IMAGE_VXD_HEADER, pDosHdr, LE2HE32(pDosHdr->e_lfanew));
if (pVxdHdr->e32_magic == HE2LE16(0x454C) && pVxdHdr->endian == 0) // Is it a little-endian VXD?
{
UINT minvsvi16 = 2 + 2 + 16, minvsffi = 52, minressecsize = ((1 + 2) + (1 + 2) + 2 + 4) + minvsvi16 + minvsffi;
PMINI_IMAGE_VXD_HEADER pLEHdr = pVxdHdr;
UINT ressecsize = LE2HE32(pLEHdr->e32_winreslen);
if (ressecsize >= minressecsize && pLEHdr->e32_winresoff != 0)
{
// MSKB201685 just assumes that the first item is the version and we do the same.
char *pRes = MKPTR(char*, pDosHdr, LE2HE32(pLEHdr->e32_winresoff));
UINT ressize, ofs = 3, succ = *MKPTR(BYTE*, pRes, 0) == 0xff && *MKPTR(WORD*, pRes, 1) == HE2LE16(16); // RT_VERSION
if (succ) succ = *MKPTR(BYTE*, pRes, ofs) == 0xff ? (ofs += (1 + 2) + 2) : (ofs += (strlen(MKPTR(char*, pRes, ofs)) + !0) + 2); // Ordinal or string name
if (succ) succ = ofs + 4 < ressecsize;
if (succ) ressize = LE2HE32(*MKPTR(DWORD*, pRes, ofs)), ofs += 4;
if (succ && ressize >= minvsvi16 + minvsffi && ressize < ressecsize)
{
WORD *pVSVI = MKPTR(WORD*, pRes, ofs); // VS_VERSIONINFO (16-bit/ASCII version)
if (LE2HE16(pVSVI[0]) >= minvsvi16 + minvsffi && LE2HE16(pVSVI[1]) >= minvsffi && !memcmp(&pVSVI[2], "VS_VERSION_INFO", 16))
{
VS_FIXEDFILEINFO *pFFI = MKPTR(VS_FIXEDFILEINFO*, pVSVI, 2 + 2 + 16);
if (LE2HE32(pFFI->dwSignature) == 0xFEEF04BD)
{
high = LE2HE32(pFFI->dwFileVersionMS), low = LE2HE32(pFFI->dwFileVersionLS);
found = true;
}
}
}
}
}
}
CloseMemMapFileView(map);
}
return found;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment