Is there a library I can use in Linux that will return the properties of a Windows EXE file that are listed in Explorer's Version tab? These are fields like Product Name, Product Version, Description, etc.
For my project, the EXE file can be only read from memory, not from a file. I would like to avoid writing the EXE file to disk.
Install winelib http://www.winehq.org/docs/winelib-guide/index This is port of MS Windows API to others systems, including linux.
Then use MS Windows API. Like
GetFileVersionInfo
http://msdn.microsoft.com/en-us/library/windows/desktop/ms647003(v=vs.85).aspxOr any other functions.
I never did it, but I would start with these findings.
Regarding exe file in memory constraint, can you copy it to RAM disk?
The version of the file is in the
VS_FIXEDFILEINFO
struct, but you have to find it into the executable data. There are two ways of doing what you want:VS_FIXEDFILEINFO
struct directly..rsrc
section, parse the resource tree, find theRT_VERSION
resource, parse it and extract theVS_FIXEDFILEINFO
data.The first one is easier, but susceptible to find the signature by chance in the wrong place. Moreover, the other data you ask for (product name, description, etc.) are not in this structure, so I'll try to explain how to obtain the data the hard way.
The PE format is a bit convoluted so I'm pasting the code piece by piece, with comments, and with minimum error checking. I'll write a simple function that dumps the data to the standard output. Writing it as a proper function is left as an exercise to the reader :)
Note that I will be using offsets in the buffer instead of mapping the structs directly to avoid portability problems related to the alignment or padding of the struct fields. Anyway, I've annotated the type of the structs used (see include file winnt.h for details).
First a few useful declarations, they should be self-explanatory:
Then a function that finds the Version resource in the executable image (no size checks).
The first structure in the EXE is the MZ header (for compatibility with MS-DOS).
The only field interesting in the MZ header is the offset of the PE header. The PE header is the real thing.
Actually, the PE header is quite boring, we want the COFF header, that have all the symbolic data.
We just need the following fields from this one.
The optional header is actually mandatory in an EXE and it is just after the COFF. The magic is different for 32 and 64 bits Windows. I'm assuming 32 bits from here on.
Here comes the interesting part: we want to find the resources section. It has two parts: 1. the section data, 2. the section metadata.
The data location is in a table at the end of the optional header, and each section has a well known index in this table. Resource section is in index 2, so we obtain the virtual address (VA) of the resource section with:
To get the section metadata we need to iterate the section table looking for a section named
.rsrc
.The section struct has two relevant members: the VA of the section and the offset of the section into the file (also the size of the section, but I'm not checking it!):
Now the offset in the file that correspond to the
vaRes
VA we got before is easy.This is a pointer to the resource data. All the individual resources are set up in the form of a tree, with 3 levels: 1) type of resource, 2) identifier of resource, 3) language of resource. For the version we will get the very first one of the correct type.
First, we have a resource directory (for the type of resource), we get the number of entries in the directory, both named and unnamed and iterate:
For each resource entry we get the type of the resource and discard it if it is not the RT_VERSION constant (16).
If it is a RT_VERSION we get to the next resource directory in the tree:
And go on to the next directory level, we don't care about the id. of this one:
The third level has the language of the resource. We don't care either, so just grab the first one:
And we get to the real resource, well, actually a struct that contains the location and size of the real resource, but we don't care about the size.
That's the VA of the version resouce, that is converted into a pointer easily.
And done! If not found return
NULL
.Now that the version resource is found, we have to parse it. It is actually a tree (what else) of pairs "name" / "value". Some values are well known and that's what you are looking for, just do some test and you will find out which ones.
NOTE: All strings are stored in UNICODE (UTF-16) but my sample code does the dumb conversion into ASCII. Also, no checks for overflow.
The function takes the pointer to the version resource and the offset into this memory (0 for starters) and returns the number of bytes analyzed.
First of all the offset have to be a multiple of 4.
Then we get the properties of the version tree node.
The name of the node is a Unicode zero-terminated string.
More padding, if neccesary:
If
type
is not 0, then it is a string version data.Else, if the name is
VS_VERSION_INFO
then it is aVS_FIXEDFILEINFO
struct. Else it is binary data.I'm just printing the version of the file and product, but you can find the other fields of this struct easily. Beware of the mixed endian order.
Now do the recursive call to print the full tree.
And some more padding before returning.
Finally, as a bonus, a
main
function.I've tested it with a few random EXEs and it seems to work just fine.
I know
pev
is a tool on Ubuntu that allows you to see this information, along with a lot of other PE header info. I also know it's written in C. Maybe you'll want to have a look at it. A bit from its history section in the docs:Here is an example in the Tcl language to parse through a .exe file to retrieve the version information.
Reading version information from Win32 executables.
This web page describes the .exe header format. I am not sure of the date of this information or whether it applies to more recent versions of Windows or not. However it is a starting place.
Here is a patch for code to support PE32+. Tested on some files and seems to work.