View Single Post
Old 15th May 2007, 04:18   #1
sbabineau
Junior Member
 
Join Date: May 2007
Posts: 7
Question Reading PE version info strings: Need another pair of eyes..

I've been racking my brain for a couple days on this one function.

The purpose is to read the file info strings from an executable (or dll, ocx, etc). Not all executables have them, but if you right-click on an executable, select Properties, then click the Version tab (if it's there) you will see the information I am trying to retrieve.

Once fixed, I think it makes a good candidate for a NSIS Example wiki page..

Anyway, I'm messing with the stack and the System plugin and it is wreaking havoc on my program throwing spurious "invalid opcode" and "Access denied" (while reading a memory address). Can someone else take a look at this with me and help me figure it out?

I think the key to fixing the problem is near the "System::Call "*$4(&t$5 .r7)"" line. When I comment that out all my problems seem to disappear. What am I doing wrong?

code:

Var PROGRAMINFO

; Call like this:
; !insertmacro GetInfoFromExeHeader "ProductName" "c:\programs\myexecutable.exe"
!macro GetInfoFromExeHeader DataType ProgramExe
Push ${DataType}
Push ${ProgramExe}
Call GetInfoFromExeHeader
Pop $PROGRAMINFO
!macroend

Function GetInfoFromExeHeader
; Valid Data Types:
; ProductName
; InternalName
; ProductVersion
; SpecialBuild
; PrivateBuild
; LegalCopyright
; LegalTrademarks
; Comments
; CompanyName
; FileVersion
; FileDescription

Exch $R0 ; path to EXE
IfFileExists $R0 +4 0
MessageBox MB_OK "$R0 doesn't exist! Please correct this."
Exch $R0 ; Put the path back on the stack
Return

Exch
Exch $R1 ; Data type

Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
Push $7

StrCpy $1 "0"
StrCpy $3 "0"
StrCpy $7 ""
StrCpy $2 "0"

System::Call "version::GetFileVersionInfoSize(t '$R0', t /NUL) i .r2" ;returns size of version block in header
IntCmp $2 0 Done Done 0 ; $2 needs to be greater than 0
System::Call "version::GetFileVersionInfo(t '$R0', i 0, i r2, *i .r3) i .r1" ; returns 1 or 0 with r3 being the fileinfo struct
IntCmp $1 0 Done 0 0 ; $1 needs to be <> 0
System::Call "version::VerQueryValue(*i r3, t '\StringFileInfo\040904E4\$R1', *i .r4, *i .r5) i .r6"
IntCmp $6 0 Done 0 0 ; $6 needs to be <> 0
IntCmp $5 0 Done Done 0
;IntOp $5 $5 + 1
System::Call "*$4(&t$5 .r7)"

Done:
System::Free $R0
System::Free $R1
System::Free $1
System::Free $2
System::Free $3
System::Free $4
System::Free $5
System::Free $6

;SetPluginUnload "manual"
Push $7

Exch 9 ; put $7 on the bottom
Pop $7
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $R0
Pop $R1
FunctionEnd



Documentation on the three version functions:

GetFileVersionInfoSize: http://msdn2.microsoft.com/en-us/library/ms647005.aspx

GetFileVersionInfo: http://msdn2.microsoft.com/en-us/library/ms647003.aspx

VerQueryValue: http://msdn2.microsoft.com/en-us/library/ms647464.aspx

-Steve.

Last edited by Anders; 9th April 2015 at 17:54. Reason: Title change
sbabineau is offline   Reply With Quote