Hi! I'm trying to write some code to check and display a programs File version info in a messagebox (like 1.1.103.1)

I'm doing it like this, but I can't get it to work, any one have any ideas?

-----------------------
[...]

.data
FileInfo VS_FIXEDFILEINFO <0,0,0,0,0,0,0,0,0,0,0,0,0>
FileDelimiter db "\",0
VersionDelimiter db ".",0
FileName db "file.exe"
.data?
InfoSize DWORD ?
FileInfoSize DWORD ?
NotUsed DWORD ?
MajorVer1 DWORD ?
MajorVer2 DWORD ?
MinorVer1 DWORD ?
MinorVer2 DWORD ?
VersionBuffer db 20 dup(?)
VersionMemPtr dd ?
PathBuffer db 1024 dup(?) ; Contains the full path and filename of the file to check.

.code

[...]

INVOKE GetFileVersionInfoSize,OFFSET PathBuffer,OFFSET NotUsed
mov InfoSize,eax
.IF InfoSize==0
; Show error message
.ELSE
INVOKE GlobalAlloc,GMEM_FIXED,OFFSET InfoSize
mov VersionMemPtr,eax
.IF eax==NULL
; Show error message
.ELSE
INVOKE GetFileVersionInfo,OFFSET PathBuffer,0,OFFSET InfoSize,OFFSET VersionMemPtr
.IF eax==0
; Show error message
.ENDIF
INVOKE VerQueryValue,OFFSET VersionMemPtr,OFFSET FileDelimiter,OFFSET FileInfo,OFFSET FileInfoSize
.IF eax==0
; Show error message
.ENDIF
mov MajorVer1,OFFSET FileInfo.dwProductVersionMS
shr MajorVer1,16
mov MajorVer2,OFFSET FileInfo.dwProductVersionMS
and MajorVer2,0FFFFh
mov MinorVer1,OFFSET FileInfo.dwProductVersionLS
shr MinorVer1,16
mov MinorVer2,OFFSET FileInfo.dwProductVersionLS
and MinorVer2,0FFFFh
INVOKE GlobalFree,OFFSET VersionMemPtr
INVOKE lstrcat,OFFSET VersionBuffer,MajorVer1
INVOKE lstrcat,OFFSET VersionBuffer,OFFSET VersionDelimiter
INVOKE lstrcat,OFFSET VersionBuffer,MajorVer2
INVOKE lstrcat,OFFSET VersionBuffer,OFFSET VersionDelimiter
INVOKE lstrcat,OFFSET VersionBuffer,MinorVer1
INVOKE lstrcat,OFFSET VersionBuffer,OFFSET VersionDelimiter
INVOKE lstrcat,OFFSET VersionBuffer,MinorVer2
INVOKE lstrcat,OFFSET VersionBuffer,InfoSize
INVOKE MessageBox,0,OFFSET VersionBuffer,OFFSET szMessageBoxConfirmationCaption,MB_OK or MB_ICONINFORMATION or MB_SYSTEMMODAL
.ENDIF
.ENDIF

-------

If I have forgotten something it's because I'm dead tired. :) Any help is greatly appreciated. If I do it like this I just get "..." in my messagebox, looks like I'm doing something wrong with the pointer to my VS_FIXEDFILEINFO struct, but I can't figure out what it is.
Posted on 2001-12-25 21:32:03 by EvilElvis


...
[b]INVOKE lstrcat,OFFSET VersionBuffer,MajorVer1[/b]
INVOKE lstrcat,OFFSET VersionBuffer,OFFSET VersionDelimiter
[b]INVOKE lstrcat,OFFSET VersionBuffer,MajorVer2[/b]
INVOKE lstrcat,OFFSET VersionBuffer,OFFSET VersionDelimiter
[b]INVOKE lstrcat,OFFSET VersionBuffer,MinorVer1 [/b]
INVOKE lstrcat,OFFSET VersionBuffer,OFFSET VersionDelimiter
...


These lines are not correct. MajorVer1, 2 etc. are no strings, they are just 32-bit (dword) values. So you can't concatenate them to a string. First, convert the number into a *string* with dwtoa (from the m32library (masm32.lib/.inc)), then use lstrcat to add it to the string.
But a better method is to use wsprintf for this (look this function up in your reference or at msdn.microsoft.com). With this function you can specify a string format and use values or other strings to fill it, like this:



.data
outFormat db "%lu.%lu.%lu",0
; %lu stands for 'long (32-bit) unsigned integer'
.code
invoke wsprintf, addr outputBuffer, addr outFormat, Version1, Version2, Version3


Thomas
Posted on 2001-12-26 17:03:48 by Thomas
Hi Thomas! Thanks for your help, that part works great now, but I still have a problem with this API call: VerQueryValue.

This is the spec for this function according to MSDN:
BOOL VerQueryValue(
const LPVOID pBlock, // buffer for version resource
LPTSTR lpSubBlock, // value to retrieve
LPVOID *lplpBuffer, // buffer for version value pointer
PUINT puLen // version length
);


And this is how I call it:
INVOKE VerQueryValue,OFFSET VersionMemPtr,OFFSET FileDelimiter,OFFSET FileInfo,OFFSET FileInfoSize

I obtain the VersionMemPtr this way:
INVOKE GlobalAlloc,GMEM_FIXED,OFFSET InfoSize
mov VersionMemPtr,eax

and it's declared like this:
VersionMemPtr dd ?

FileDelimiter is just a variable declared like this:
FileDelimiter db "\",0

FileInfoSize is decalred like this:
FileInfoSize DWORD ?

I think it's the LPVOID *lplpBuffer part that I don't get to work correctly. I declared FileInfo like this:
FileInfo VS_FIXEDFILEINFO <0,0,0,0,0,0,0,0,0,0,0,0,0>

But after reading more carefully it looks like the function wants a pointer to a variable thats a pointer to a VS_FIXEDFILEINFO.

So I guess my question is, how do I achieve that? This is what MSDN has to say about lplpBuffer:

lplpBuffer
Pointer to a variable that receives a pointer to the requested version information in the buffer pointed to by pBlock. The memory pointed to by *lplpBuffer is freed when the associated pBlock memory is freed.

Any help is greatly appreciated.

Thanks again for your help Thomas and a Happy New Year to all of you! :)
Posted on 2002-01-01 10:20:53 by EvilElvis
I obtain the VersionMemPtr this way:
INVOKE GlobalAlloc,GMEM_FIXED,OFFSET InfoSize
mov VersionMemPtr,eax

and it's declared like this:
VersionMemPtr dd ?


This should be INVOKE GlobalAlloc,GMEM_FIXED, InfoSize
'OFFSET InfoSize' is the address of the InfoSize variable, not the contents of it. (change it in your old code as well)

Also, pBlock is an *input* parameter, so giving it an empty memory block has no use. You'll have to call GetFileVersionInfo to fill that new memory block. But you already did that in your previous code so just use the old VersionMemPtr (do not allocate new memory) you already filled in your previous code.

Finally, lplpBuffer is a *pointer* to a *dword var* that will receive a *pointer* to the info. So fileinfo has to be:

FileInfo dd ?

And use 'offset FileInfo' as parameter in the call.
On return the value in FileInfo will be a pointer to the information.

Thomas
Posted on 2002-01-01 14:43:52 by Thomas