loot / libloot

A C++ library for accessing LOOT's metadata and sorting functionality.
GNU General Public License v3.0
32 stars 12 forks source link

product_version evaluation returning incorrect result #45

Closed MacSplody closed 5 years ago

MacSplody commented 5 years ago

I did some testing of the product version check with the latest bintray build, and it doesn't seem to be evaluating correctly. I was testing if SkyrimSE.exe was the latest version, and that was not showing when true. I was also testing if it was an old version, and that message was showing.

Tested using: Bintray snapshot loot_0.13.6-28-gb8badfc_dev SkyrimSE.exe

image


  - <<: *hasOldVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1.5.62.0", <) and file("../SkyrimSE.exe")'
  - <<: *hasLatestVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1.5.62.0", ==) and file("../SkyrimSE.exe")'

hasOldVersionOfX showing with above conditions.

image


If I switch the conditions.

  - <<: *hasOldVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1.5.62.0", ==) and file("../SkyrimSE.exe")'
  - <<: *hasLatestVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1.5.62.0", <) and file("../SkyrimSE.exe")'

The hasLatestVersionOfX message will show.

image

MacSplody commented 5 years ago
  - <<: *hasOldVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1", ==) and file("../SkyrimSE.exe")'
  - <<: *hasLatestVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1", ==) and file("../SkyrimSE.exe")'

Above yields the following result. image

Ortham commented 5 years ago

This is probably thanks to each version number appearing twice in SkyrimSE.exe. LOOT reads from the fixed-size version fields, but there are also string version fields, and in SkyrimSE.exe's case, they don't match. Both fixed-size fields (file and product) are 1.0.0.0, but the string fields are:

{"ProductVersion": "1.5.62.0", "CompanyName": "Bethesda Softworks", "FileDescription": "Skyrim", "LegalCopyright": "Copyright 2009-2012 ZeniMax Media Incorporated. All Rights Reserved.", "OriginalFilename": "TESV.exe", "InternalName": "Skyrim", "ProductName": "TESV: Skyrim", "FileVersion": "1.5.62.0"}

Note that if you use just the fixed fields, they don't match what File Explorer shows, but if you use the strings, they also don't match, so File Explorer seems to be picking the fixed file version and the string product version...

Ortham commented 5 years ago

I've quickly knocked together a little utility to help see what's in the various fields of a given executable: version-check.zip (repository here).

I'm going to run this against as many executables we currently check versions of as I can reasonably get hold of, but if you want to help, running it against whatever you've got might cover things I miss.

MacSplody commented 5 years ago

SkyrimSE

Launchers
Some(VS_FIXEDFILEINFO{dwSignature : 4277077181, dwStrucVersion : 65536, dwFileVersion : VS_VERSION{Minor : 0, Major : 1, Build : 0, Patch : 0
    }, dwProductVersion : VS_VERSION{Minor : 0, Major : 1, Build : 0, Patch : 0
    }, dwFileFlagsMask : 23, dwFileFlags : 0, dwFileOS : 4, dwFileType : 1, dwFileSubtype : 0, dwFileDateMS : 0, dwFileDateLS : 0
})
{
    "LegalCopyright": "Copyright 2009-2012 ZeniMax Media Incorporated. All Rights Reserved.",
    "OriginalFilename": "TESV.exe",
    "FileVersion": "1.5.62.0",
    "FileDescription": "Skyrim",
    "CompanyName": "Bethesda Softworks",
    "ProductVersion": "1.5.62.0",
    "InternalName": "Skyrim",
    "ProductName": "TESV: Skyrim"
}

Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 0, Major: 1, Build: 0, Patch: 0
    }, dwProductVersion: VS_VERSION { Minor: 0, Major: 1, Build: 0, Patch: 0
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "ProductName": "The Elder Scrolls V: Skyrim Special Edition Launcher",
    "CompanyName": "Bethesda Softworks",
    "LegalCopyright": "Copyright 2016 ZeniMax Media Incorporated. All Rights Reserved.",
    "FileDescription": "The Elder Scrolls V: Skyrim Special Edition Launcher",
    "ProductVersion": "1.0.0.0",
    "FileVersion": "1.0.0.0",
    "InternalName": "SkyrimSELauncher",
    "OriginalFilename": "SkyrimSELauncher.exe"
}
SKSE 64
Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 2, Major: 0, Build: 12, Patch: 0
    }, dwProductVersion: VS_VERSION { Minor: 2, Major: 0, Build: 12, Patch: 0
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})`
{
    "InternalName": "SKSE64",
    "FileDescription": "A component of the Skyrim SE Script Extender",
    "FileVersion": "0, 2, 0, 12",
    "LegalCopyright": "Copyright (C) 2006-2018",
    "ProductVersion": "0, 2, 0, 12",
    "ProductName": "SKSE64"
}

Skyrim LE

Launchers
Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 9, Major: 1, Build: 0, Patch: 32
    }, dwProductVersion: VS_VERSION { Minor: 9, Major: 1, Build: 0, Patch: 32
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "CompanyName": "Bethesda Softworks",
    "FileVersion": "1.9.32.0",
    "InternalName": "Skyrim",
    "FileDescription": "Skyrim",
    "OriginalFilename": "TESV.exe",
    "ProductName": "TESV: Skyrim",
    "ProductVersion": "1.9.32.0"
}

Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 3, Major: 1, Build: 0, Patch: 22
    }, dwProductVersion: VS_VERSION { Minor: 3, Major: 1, Build: 0, Patch: 22
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "OriginalFilename": "SkyrimLauncher.exe",
    "InternalName": "SkyrimLauncher",
    "ProductName": "Skyrim Launcher",
    "CompanyName": "Bethesda Softworks",
    "LegalCopyright": "Copyright 2012 ZeniMax Media Incorporated. All Rights Reserved.",
    "FileVersion": "1.3.22.0",
    "FileDescription": "Skyrim Launcher",
    "ProductVersion": "1.3.22.0"
}
SKSE
Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 1, Major: 0, Build: 3, Patch: 7
    }, dwProductVersion: VS_VERSION { Minor: 1, Major: 0, Build: 3, Patch: 7
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "ProductVersion": "0, 1, 7, 3",
    "InternalName": "SKSE",
    "LegalCopyright": "Copyright (C) 2006-2015",
    "FileVersion": "0, 1, 7, 3",
    "ProductName": "SKSE",
    "FileDescription": "A component of the Skyrim Script Extender"
}
MacSplody commented 5 years ago

Oblivion

Launchers
Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 2, Major: 1, Build: 416, Patch: 0
    }, dwProductVersion: VS_VERSION { Minor: 2, Major: 1, Build: 416, Patch: 0
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "CompanyName": "Bethesda Softworks",
    "FileDescription": "Oblivion",
    "InternalName": "Oblivion",
    "ProductVersion": "1.2.0416",
    "ProductName": "TES4: Oblivion",
    "LegalCopyright": "Copyright © 2006 ZeniMax Media Incorporated. All Rights Reserved.",
    "FileVersion": "1.2.0416",
    "OriginalFilename": "Oblivion.exe"
}
OblivionLauncher

PS D:\GOG Galaxy\Games\Oblivion> .\version-check.exe OblivionLauncher.exe thread 'main' panicked at 'Failed to read executable versions.: PeParsingError("OblivionLauncher.exe", NotFound)', libcore\result.rs:1009:5 note: Run withRUST_BACKTRACE=1for a backtrace. PS D:\GOG Galaxy\Games\Oblivion>

OBSE Steam
Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 0, Major: 0, Build: 4, Patch: 21
    }, dwProductVersion: VS_VERSION { Minor: 0, Major: 0, Build: 4, Patch: 21
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "InternalName": "obse",
    "ProductName": "obse",
    "FileDescription": "A component of the Oblivion Script Extender",
    "LegalCopyright": "Copyright (C) 2006-2013",
    "ProductVersion": "0, 0, 21, 4",
    "FileVersion": "0, 0, 21, 4"
}
OBSE GOG
Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 0, Major: 0, Build: 4, Patch: 21
    }, dwProductVersion: VS_VERSION { Minor: 0, Major: 0, Build: 4, Patch: 21
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "ProductVersion": "0, 0, 21, 4",
    "FileVersion": "0, 0, 21, 4",
    "FileDescription": "A component of the Oblivion Script Extender",
    "ProductName": "obse",
    "InternalName": "obse",
    "LegalCopyright": "Copyright (C) 2006-2013"
}

Fallout 3 GOTY

Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 7, Major: 1, Build: 3, Patch: 0
    }, dwProductVersion: VS_VERSION { Minor: 7, Major: 1, Build: 3, Patch: 0
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "OriginalFilename": "Fallout3.exe",
    "InternalName": "Fallout3",
    "ProductName": "Fallout 3",
    "CompanyName": "Bethesda Softworks",
    "LegalCopyright": "Copyright  2006 ZeniMax Media Incorporated. All Rights Reserved.",
    "FileDescription": "Fallout3",
    "ProductVersion": "1.7.0.3",
    "FileVersion": "1.7.0.3"
}

Fallout New Vegas

Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 4, Major: 1, Build: 525, Patch: 0
    }, dwProductVersion: VS_VERSION { Minor: 4, Major: 1, Build: 525, Patch: 0
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "ProductName": "Fallout: New Vegas",
    "LegalCopyright": "Copyright  2010 ZeniMax Media Incorporated. All Rights Reserved.",
    "FileVersion": "1.4.0.525",
    "ProductVersion": "1.4.0.525",
    "FileDescription": "FalloutNV",
    "OriginalFilename": "FalloutNV.exe",
    "InternalName": "FalloutNV",
    "CompanyName": "Bethesda Softworks"
}

Fallout 4

Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 10, Major: 1, Build: 0, Patch: 120
    }, dwProductVersion: VS_VERSION { Minor: 10, Major: 1, Build: 0, Patch: 120
    }, dwFileFlagsMask: 23, dwFileFlags: 0, dwFileOS: 4, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "OriginalFilename": "Fallout4.exe",
    "LegalCopyright": "Copyright 2012 ZeniMax Media Incorporated. All Rights Reserved.",
    "ProductName": "Fallout 4",
    "ProductVersion": "1.10.120.0",
    "InternalName": "Institute",
    "FileVersion": "1.10.120.0",
    "CompanyName": "Bethesda Softworks",
    "FileDescription": "Fallout 4"
}

Morrowind

Some(VS_FIXEDFILEINFO { dwSignature: 4277077181, dwStrucVersion: 65536, dwFileVersion: VS_VERSION { Minor: 6, Major: 1, Build: 1820, Patch: 0
    }, dwProductVersion: VS_VERSION { Minor: 6, Major: 1, Build: 1820, Patch: 0
    }, dwFileFlagsMask: 63, dwFileFlags: 0, dwFileOS: 262148, dwFileType: 1, dwFileSubtype: 0, dwFileDateMS: 0, dwFileDateLS: 0
})
{
    "CompanyName": "Bethesda Softworks",
    "ProductVersion": "1.6.1820",
    "InternalName": "Morrowind",
    "OriginalFilename": "Morrowind.exe",
    "LegalTrademarks": "",
    "Comments": "                                                                                                  ",
    "ProductName": "Bethesda Softworks Morrowind",
    "SpecialBuild": "",
    "PrivateBuild": "",
    "LegalCopyright": "Copyright © 2002 ZeniMax Media Incorporated. All Rights Reserved.",
    "FileVersion": "1.6.1820",
    "FileDescription": "Morrowind"
}
Ortham commented 5 years ago

Wow, thanks for doing all those, you got to them before I could! I've summarised the version numbers in the table below.

Executable Fixed File Version Fixed Product Version String File Version String Product Version
SkyrimSE.exe 1.0.0.0 1.0.0.0 1.5.62.0 1.5.62.0
SkyrimSELauncher.exe 1.0.0.0 1.0.0.0 1.0.0.0 1.0.0.0
SKSE 64 0.2.0.12 0.2.0.12 0.2.0.12 0.2.0.12
TESV.exe 1.9.32.0 1.9.32.0 1.9.32.0 1.9.32.0
SkyrimLauncher.exe 1.3.22.0 1.3.22.0 1.3.22.0 1.3.22.0
SKSE 0.1.7.3 0.1.7.3 0.1.7.3 0.1.7.3
Oblivion.exe 1.2.0.416 1.2.0.416 1.2.0416 1.2.0416
OBSE (Steam) 0.0.21.4 0.0.21.4 0.0.21.4 0.0.21.4
OBSE (GOG) 0.0.21.4 0.0.21.4 0.0.21.4 0.0.21.4
Fallout 3 1.7.0.3 1.7.0.3 1.7.0.3 1.7.0.3 1.7.0.3
Fallout New Vegas 1.4.0.525 1.4.0.525 1.4.0.525 1.4.0.525
Fallout 4 1.10.120.0 1.10.120.0 1.10.120.0 1.10.120.0
Morrowind 1.6.0.1820 1.6.0.1820 1.6.1820 1.6.1820

Bolded cells highlight the value displayed by File Explorer where the values aren't all the same. It looks like File Explorer displays the fixed file version and the string product version, so I'll change LOOT's logic to do the same.

Ortham commented 5 years ago

@CptMcSplody try with this DLL.

MacSplody commented 5 years ago

@Ortham

I think it's working as expected now.

  - <<: *hasOldVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1.5.62.0", <) and file("../SkyrimSE.exe")'
  - <<: *hasLatestVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1.5.62.0", ==) and file("../SkyrimSE.exe")'

image

Test with dummy version "9.9.9.9"

  - <<: *hasOldVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "9.9.9.9", <) and file("../SkyrimSE.exe")'
  - <<: *hasLatestVersionOfX
    subs: [ 'Skyrim SE' ]
    condition: 'product_version("../SkyrimSE.exe", "1", ==) and file("../SkyrimSE.exe")'

Result

image