NSIS/Contrib/Library/LibraryLocal/LibraryLocal.cpp
2007-04-17 18:30:30 +00:00

222 lines
3.8 KiB
C++

/*
LibraryLocal - used by the Library.nsh macros
Get the version of local DLL and TLB files
Written by Joost Verburg
*/
#include "../../../Source/Platform.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include "../../../Source/ResourceEditor.h"
#include "../../../Source/ResourceVersionInfo.h"
#include "../../../Source/winchar.h"
using namespace std;
int g_noconfig=0;
int g_display_errors=1;
FILE *g_output=stdout;
int GetDLLVersion(string& filepath, DWORD& high, DWORD & low)
{
int found = 0;
FILE *fdll = fopen(filepath.c_str(), "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;
}
try
{
CResourceEditor *dllre = new CResourceEditor(dll, len);
LPBYTE ver = dllre->GetResourceA(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0);
int versize = dllre->GetResourceSizeA(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0);
if (ver)
{
if ((size_t) versize > sizeof(WORD) * 3)
{
// get VS_FIXEDFILEINFO from VS_VERSIONINFO
WCHAR *szKey = (WCHAR *)(ver + sizeof(WORD) * 3);
int len = (winchar_strlen(szKey) + 1) * sizeof(WCHAR) + sizeof(WORD) * 3;
len = (len + 3) & ~3; // align on DWORD boundry
VS_FIXEDFILEINFO *verinfo = (VS_FIXEDFILEINFO *)(ver + len);
if (versize > len && verinfo->dwSignature == VS_FFI_SIGNATURE)
{
low = verinfo->dwFileVersionLS;
high = verinfo->dwFileVersionMS;
found = 1;
}
}
dllre->FreeResource(ver);
}
delete dllre;
}
catch (exception&)
{
return 0;
}
return found;
}
int GetTLBVersion(string& filepath, DWORD& high, DWORD & low)
{
#ifdef _WIN32
int found = 0;
char fullpath[1024];
char *p;
if (!GetFullPathName(filepath.c_str(), sizeof(fullpath), fullpath, &p))
return 0;
wchar_t ole_filename[1024];
MultiByteToWideChar(CP_ACP, 0, fullpath, lstrlen(fullpath) + 1, ole_filename, 1024);
ITypeLib* typeLib;
HRESULT hr;
hr = LoadTypeLib(ole_filename, &typeLib);
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
}
int main(int argc, char* argv[])
{
// Parse the command line
string cmdline;
string mode;
string filename;
string filepath;
int filefound = 0;
if (argc != 4)
return 1;
// Get the full path of the local file
mode = argv[1];
filename = argv[2];
// Validate filename
ifstream fs(filename.c_str());
if (fs.is_open())
{
filefound = 1;
fs.close();
}
// Work
int versionfound = 0;
DWORD low = 0, high = 0;
if (filefound)
{
// Get version
// DLL
if (mode.compare("D") == 0)
{
versionfound = GetDLLVersion(filename, high, low);
}
// TLB
if (mode.compare("T") == 0)
{
versionfound = GetTLBVersion(filename, high, low);
}
}
// Write the version to an NSIS header file
ofstream header(argv[3], ofstream::out);
if (header)
{
if (!filefound)
{
header << "!define LIBRARY_VERSION_FILENOTFOUND" << endl;
}
else if (!versionfound)
{
header << "!define LIBRARY_VERSION_NONE" << endl;
}
else
{
header << "!define LIBRARY_VERSION_HIGH " << high << endl;
header << "!define LIBRARY_VERSION_LOW " << low << endl;
}
header.close();
}
return 0;
}