Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Reply
Thread Tools Search this Thread Display Modes
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
Old 15th May 2007, 05:05   #2
Red Wine
Forum King
 
Red Wine's Avatar
 
Join Date: Mar 2006
Location: Ath. GR
Posts: 2,078
Have you seen the MoreInfo plugin? It's so easy

http://nsis.sourceforge.net/MoreInfo_plug-in

Quick AVI Creator - Quick and easy convert from DVD/MPEG/AVI/MKV to AVI/MP4/MKV
Quick AVI Creator entirely edited with NSIS and entirely upgraded to Unicode NSIS
Red Wine is offline   Reply With Quote
Old 15th May 2007, 18:36   #3
kichik
M.I.A.
[NSIS Dev, Mod]
 
kichik's Avatar
 
Join Date: Oct 2001
Location: Israel
Posts: 11,343
  1. File path may contain quotes, so it's better to use R0 instead of '$R0' when passing it to System::Call.
  2. /NUL is not a valid parameter. Either use n for NULL or pass a real pointer.
  3. You must allocate a buffer for GetFileVersionInfo with System::Alloc. You just passed it pointer to an integer which it fills and then some. That's corrupting the heap.
Quote:
Once fixed, I think it makes a good candidate for a NSIS Example wiki page..
Everything makes a good candidate for that. Feel free to create Wiki pages with what you'd consider useful information.

NSIS FAQ | NSIS Home Page | Donate $
"I hear and I forget. I see and I remember. I do and I understand." -- Confucius
kichik is offline   Reply With Quote
Old 9th April 2015, 10:43   #4
stass
Senior Member
 
Join Date: Nov 2012
Posts: 146
Why MoreInfo plugin gives false information in the file vcredist_x86.exe (MicrosoftVisual C ++ 2012 Redistributable) ?
https://www.microsoft.com/ru-ru/down....aspx?id=30679

PHP Code:
!addplugindir .
OutFile 'MoreInfo-test.exe'
var a
var b
Section
strcpy 
$"$EXEDIR\vcredist_x86.exe"
  
MoreInfo::GetProductName "$1"
  
Pop $a
  StrCpy 
$"$0$\r$\n - ProductName: $a"
  
  
MoreInfo::GetFileVersion "$1"
  
Pop $b
  StrCpy 
$"$0$\r$\n - GetFileVersion: $b"

MessageBox MB_OK|MB_ICONINFORMATION "$0"
SectionEnd 


How to fix it?

question 2 :

How to "make friends" "FileVerInfo.nsh" and "FileFunc.nsh" ?
When used together, getting the error ...
stass is offline   Reply With Quote
Old 9th April 2015, 16:02   #5
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,191
Quote:
Originally Posted by stass View Post
Why MoreInfo plugin gives false information in the file vcredist_x86.exe (MicrosoftVisual C ++ 2012 Redistributable) ?
How to fix it?

question 2 :

How to "make friends" "FileVerInfo.nsh" and "FileFunc.nsh" ?
When used together, getting the error ...
Are you mixing Unicode and Ansi installers and plugins? Are you using NSIS 3? Please provide more information when asking questions.

What is FileVerInfo.nsh and where did you download it?

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 9th April 2015, 16:33   #6
stass
Senior Member
 
Join Date: Nov 2012
Posts: 146
Anders
I thought it was your product ...
http://www.mediafire.com/?n6w4b6nqcgrrh8z
Incompatibility disappeared when commenting line 97
Problem with MoreInfo plugin - remained. NSIS 3b. With encodings - all right.
stass is offline   Reply With Quote
Old 9th April 2015, 17:46   #7
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,191
I'm guessing there can be 4 reasons why it is not working:

1) The version info in that .exe is broken/corrupt (Unlikely)
2) A bug in the plugin
3) A bug in NSIS
4) Programmer error; mixing Ansi/Unicode compiler/plugins (This is my guess)

To find the answer I would have to be able to reproduce the problem and since I don't want to waste too much time on this I would need some extra pieces of information:

1) Exact NSIS version (And is it a special build?)
2) Exact plugin version (The wiki has two zip files, one of the zip files has both Ansi and Unicode builds)
3) The value of the Unicode and RequestExecutionLevel attributes used in your script

And as a side note; a Unicode string displayed by Ansi code/functions will end up as a single character most of the time and this is a strong indication that you are mixing Ansi/Unicode stubs/plugins. Ansi strings displayed by Unicode code/functions often looks like Chinese (CJK codepoints).

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 10th April 2015, 08:53   #8
stass
Senior Member
 
Join Date: Nov 2012
Posts: 146
Anders

I have installed the regular NSIS - nsis-3.0b1-setup.exe

I work with ANSI.

Accordingly, use ansi version MoreInfo plugin: \ Program Files \ NSIS \ Plugins \ x86-ansi \ MoreInfo.dll
( http://www.fdos.org/win32/nsis/plugi...fo.1.0.1.2.zip )

Script - simple as in Example .

In determining the version of the file vcredist_x86.exe - getting only the first character .

FileVerInfo.nsh determines the version of the file vcredist_x86.exe - right ! ( But only version right ... Everything else is nonsense ... )



It turns out that we have no means to obtain information about a file? Because the available plug-ins do not work with all the files ... This is very bad ...

Last edited by stass; 10th April 2015 at 11:11.
stass is offline   Reply With Quote
Old 10th April 2015, 17:32   #9
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,191
There might be something strange with the version info in that .exe after all!

Quote:
Outfile "$%Temp%\Test.exe"
Unicode false
RequestExecutionLevel user

!include LogicLib.nsh

Function GetFileVerFirstLangProductVersion
... http://pastebin.com/f5e461c4d
FunctionEnd


!define THEFILE "$Temp\X\vcredist_x86.exe" #"$windir\explorer.exe"

Section

!if "${NSIS_CHAR_SIZE}" <= 1
!addplugindir "$%Temp%\X\MoreInfo\Plugins\Ansi"
MoreInfo::GetProductName "${THEFILE}"
Pop $0
DetailPrint |$0|
!endif

Push "${THEFILE}"
Call GetFileVerFirstLangProductVersion
Pop $0
DetailPrint |$0|

SectionEnd
This fails to read correctly when compiling as Ansi but works correctly when compiled as Unicode! Reading the version info from %windir%\explorer.exe works in both.

I'm not sure if VerQueryValueA is broken or if the .exe is not following the PE spec. Either way, this bug is not in NSIS...

You can work around it like this:
Quote:
Function GetFileVerFirstNamedLangEntryOnWindowsNT
System::Store S
pop $3
pop $4
push "" ;failed ret
System::Call 'version::GetFileVersionInfoSizeW(w"$3",i.r2)i.r0'
${If} $0 <> 0
System::Alloc $0
System::Call 'version::GetFileVersionInfoW(w"$3",ir2,ir0,isr1)i.r0 ? e'
pop $2
${If} $0 <> 0
${AndIf} $2 = 0 ;a user comment on MSDN said you should check GLE to avoid crash
System::Call 'version::VerQueryValueW(i r1,w "\VarFileInfo\Translation",*i0r2,*i0)i.r0'
${If} $0 <> 0
System::Call '*$2(&i2.r2,&i2.r3)'
IntFmt $2 %04x $2
IntFmt $3 %04x $3
System::Call 'version::VerQueryValueW(i r1,w "\StringFileInfo\$2$3\$4",*i0r2,*i0r3)i.r0'
${If} $0 <> 0
pop $0
System::Call *$2(&w$3.s)
${EndIf}
${EndIf}
${EndIf}
System::Free $1
${EndIf}
System::Store L
FunctionEnd

Section
Push LegalCopyright
Push "${THEFILE}"
Call GetFileVerFirstNamedLangEntryOnWindowsNT
Pop $0
DetailPrint |$0|

Push FileDescription
Push "${THEFILE}"
Call GetFileVerFirstNamedLangEntryOnWindowsNT
Pop $0
DetailPrint |$0|
SectionEnd
...will not work on Win9x and is probably not a good idea in general, it would be better if we could figure out why the Ansi version fails...

If someone has a VM with Win95/98 it would be fun to see what Windows does there...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 11th April 2015, 07:23   #10
stass
Senior Member
 
Join Date: Nov 2012
Posts: 146
Anders, thank you very much for your help !
Now Function GetFileVerFirstNamedLangEntryOnWindowsNT works !
stass is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump