I'm trying to use ChangeVersionInfo() and VersionRes class, from HotkeyIt's rewrite of ahk2exe iirc, to create a standalone function to edit the VersionInfo of another PE binary, but haven't been successful in creating the verInfo object parameter to send to the function.
I've made some mod's to ChangeVersionInfo() to remove dependencies on other parts of ahk2exe, but I'm a total amateur with objects/classes so I was hoping one of you experts could help me out. Basically the goal would be to read the VersionInfo from a PE binary (AutoHotkeySC.bin specifically, or any compiled script), modify one or all of the values and/or add in missing values, and write it back to the resources of the binary.
Anyone done this or willing to point me in the right direction?
Thanks
Code: Select all
;ChangeVersionInfo.ahk
ChangeVersionInfo(ExeFile, hUpdate, verInfo)
{
hModule := LoadLibraryEx(ExeFile, 0, 2)
if !hModule
Util_Error("Error: Error opening destination file.")
hRsrc := DllCall("FindResource", "PTR", hModule, "PTR", 1, "PTR", 16) ; Version Info\1
hMem := LoadResource(hModule, hRsrc)
vi := new VersionRes(LockResource(hMem))
FreeLibrary(hModule)
ffi := vi.GetDataAddr()
props := SafeGetViChild(SafeGetViChild(vi, "StringFileInfo"), "040904b0")
for k,v in verInfo
{
if IsLabel(lbl := "_VerInfo_" k)
gosub %lbl%
continue
_VerInfo_Name:
SafeGetViChild(props, "ProductName").SetText(v)
SafeGetViChild(props, "InternalName").SetText(v)
return
_VerInfo_Description:
SafeGetViChild(props, "FileDescription").SetText(v)
return
_VerInfo_Version:
SafeGetViChild(props, "FileVersion").SetText(v)
SafeGetViChild(props, "ProductVersion").SetText(v)
ver := VersionTextToNumber(v)
hiPart := (ver >> 32)&0xFFFFFFFF, loPart := ver & 0xFFFFFFFF
NumPut(hiPart, ffi+8, "UInt"), NumPut(loPart, ffi+12, "UInt")
NumPut(hiPart, ffi+16, "UInt"), NumPut(loPart, ffi+20, "UInt")
return
_VerInfo_Copyright:
SafeGetViChild(props, "LegalCopyright").SetText(v)
return
_VerInfo_OrigFilename:
SafeGetViChild(props, "OriginalFilename").SetText(v)
return
_VerInfo_CompanyName:
SafeGetViChild(props, "CompanyName").SetText(v)
return
}
VarSetCapacity(newVI, 16384) ; Should be enough
viSize := vi.Save(&newVI)
if !DllCall("UpdateResource", "ptr", hUpdate, "ptr", 16, "ptr", 1
, "ushort", 0x409, "ptr", &newVI, "uint", viSize, "uint")
Util_Error("Error changing the version information.")
}
VersionTextToNumber(v)
{
r := 0, i := 0
while i < 4 && RegExMatch(v, "O)^(\d+).?", o)
{
StringTrimLeft, v, v, % o.Len
val := o[1] + 0
r |= (val&0xFFFF) << ((3-i)*16)
i ++
}
return r
}
SafeGetViChild(vi, name)
{
c := vi.GetChild(name)
if !c
{
c := new VersionRes()
c.Name := name
vi.AddChild(c)
}
return c
}
Util_ObjIsEmpty(obj)
{
for _,__ in obj
return false
return true
}
#Include <VersionRes>
Code: Select all
;VersionRes.ahk
class VersionRes
{
Name := ""
,Data := ""
,IsText := true
,DataSize := 0
,Children := []
__New(addr := 0)
{
if !addr
return this
wLength := NumGet(addr+0, "UShort"), addrLimit := addr + wLength, addr += 2
,wValueLength := NumGet(addr+0, "UShort"), addr += 2
,wType := NumGet(addr+0, "UShort"), addr += 2
,szKey := StrGet(addr, "UTF-16"), addr += 2*(StrLen(szKey)+1), addr := (addr+3)&~3
,ObjSetCapacity(this, "Data", size := wValueLength*(wType+1))
,this.Name := szKey
,this.DataSize := wValueLength
,this.IsText := wType
,DllCall("msvcrt\memcpy", "ptr", this.GetDataAddr(), "ptr", addr, "ptr", size, "cdecl"), addr += size, addr := (addr+3)&~3
; if wType
; ObjSetCapacity(this, "Data", -1)
while addr < addrLimit
{
size := (NumGet(addr+0, "UShort") + 3) & ~3
,this.Children.Insert(new VersionRes(addr))
,addr += size
}
}
_NewEnum()
{
return this.Children._NewEnum()
}
AddChild(node)
{
this.Children.Insert(node)
}
GetChild(name)
{
for k,v in this
if v.Name = name
return v
}
GetText()
{
if this.IsText
return this.Data
}
SetText(txt)
{
if A_IsUnicode
this.Data := txt
else
ObjSetCapacity(this,"Data",StrLen(txt)*2+2),StrPut(txt,this.GetDataAddr(),"UTF-16")
this.IsText := true
,this.DataSize := StrLen(txt)+1
}
GetDataAddr()
{
return ObjGetAddress(this, "Data")
}
Save(addr)
{
orgAddr := addr
,addr += 2
,NumPut(ds:=this.DataSize, addr+0, "UShort"), addr += 2
,NumPut(it:=this.IsText, addr+0, "UShort"), addr += 2
,addr += 2*StrPut(this.Name, addr+0, "UTF-16")
,addr := (addr+3)&~3
,realSize := ds*(it+1)
,DllCall("msvcrt\memcpy", "ptr", addr, "ptr", this.GetDataAddr(), "ptr", realSize, "cdecl"), addr += realSize
,addr := (addr+3)&~3
for k,v in this
addr += v.Save(addr)
size := addr - orgAddr
,NumPut(size, orgAddr+0, "UShort")
return size
}
}