Last active
October 16, 2017 19:57
-
-
Save sredna/585931b3f07813f8825a36b9d847719a to your computer and use it in GitHub Desktop.
NSIS VXD version interop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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