Skip to content

Add support for Inno Setup 6.4.2 through 6.7.1#210

Open
dscho wants to merge 11 commits into
dscharrer:masterfrom
dscho:inno-6.4-to-6.7-support
Open

Add support for Inno Setup 6.4.2 through 6.7.1#210
dscho wants to merge 11 commits into
dscharrer:masterfrom
dscho:inno-6.4-to-6.7-support

Conversation

@dscho
Copy link
Copy Markdown

@dscho dscho commented May 10, 2026

This series teaches innoextract to parse installers built with Inno Setup 6.4.2 through 6.7.1. Upstream currently bails out on the new SetupID magic strings, and even past that point the on-disk layout has changed substantially across the 6.4.x, 6.5.x, 6.6.x and 6.7.x lines (new header fields, the encryption metadata moved out of TSetupHeader into a separate outer-stream TSetupEncryptionHeader, an ISSig key array between directories and files, 64-bit offsets and sizes, dark-mode wizard image groups, padding bytes in the option bitsets, and so on). The motivation is concrete: recent Git for Windows installers are built with Inno Setup 6.7.x, and innoextract --info / --list are useful enough on those that I wanted them to keep working.

Opening as a draft because I''d like your eyes on the structural choices before polishing.

The 11 commits are split so each one builds and runs independently (verified via git rebase --exec ''ninja innoextract'' from the upstream merge-base). Each commit message cites the relevant Projects/Src/Shared.Struct.pas snippets at the corresponding is-X_Y_Z tag of https://github.com/jrsoftware/issrc as evidence, so the per-version deltas can be cross-checked against issrc directly rather than against my prose.

Roughly, the shape is: commit 1 adds the setup loader v2 offset table (Inno Setup 6.5.0+) in a minimal form that truncates back to uint32 so the seek chain need not change yet; commits 2, 3, 4 cover the simple per-version magic strings plus straightforward header field additions and the TSetupHeaderOption reshuffle through 6.6.1; commit 5 is a pure type widening of offsets, chunk_location and slice_reader::seek to 64 bits with no behaviour change; commit 6 then makes the loader-v2 path and the 6.7.0 block header consume native Int64, so >4 GiB installers are parsed without silent truncation; commit 7 adds bytes_consumed() and discard_padding_to(target) helpers on stored_flag_reader<>; commits 8, 9, 10 cover the 6.5.0 / 6.5.2 / 6.6.0 entry stream reworks (encryption header split-out, the TSetupISSigKeyEntry array, the optional 7-Zip DLL outer stream, the TSetupFileEntry and TSetupFileLocationEntry reshuffles, the 64-bit StartOffset, the TSetupLanguageEntry rework, dynamic-dark wizard images); commit 11 covers the 6.7.0 / 6.7.1 changes (the five shUsePrevious* flags promoted out of the option bitset into expression-string header fields, three new wizard colour fields, TSetupWizardLightControlStyling, the shUnusedPadding=56 / foUnusedPadding=56 padding handled via discard_padding_to(8), Level narrowing on components and tasks, and the new WizardBackImageFile image group).

A few design points worth flagging explicitly, since they are deliberate and a reviewer might otherwise pick at them:

For 6.5.0+ installers, TSetupHeader now clears password.type and password_salt rather than leaving password.type = PBKDF2_SHA256_XChaCha20. With the encryption metadata moved out to the outer-stream TSetupEncryptionHeader, leaving the in-header password type set would make --info report "Setup is passworded!" for every 6.5.0+ installer regardless of whether EncryptionUse is actually euNone. Clearing it preserves the upstream "Setup is not passworded!" output for the unencrypted case.

The 6.7.0 bitset padding is handled via flagreader.discard_padding_to(8) rather than hard-coded byte reads, so it survives future flag-count changes within innoextract itself without re-derivation of the padding constant.

ISSig keys are loaded into a proper issig_key_entry struct via the standard load_entries(...) mechanism (new src/setup/issigkey.{cpp,hpp}, new ISSigKeys entry_types flag, new info::issig_keys vector). Callers that opt in via ISSigKeys get the keys; callers that don''t get the same skip-only behaviour the inline path would have had.

The per-file ISSig SHA-256 digest is stored in the existing (and, on the relevant code path, previously unread) file_entry::checksum field rather than a newly invented verification_checksum. The trailing unconditional checksum.type = crypto::None reset is gated to < 6.5.0 so the hash survives.

Verification I ran locally: innoextract --info against a 6.7.0 Git for Windows installer reports Inspecting "Git" - setup data version 6.7.0 (unicode), Setup is not passworded!, Done., and exits 0; innoextract --list on the same installer enumerates 9409 entries, all paths within the installer; and git rebase --exec ''ninja innoextract'' from the upstream merge-base succeeds for all 11 intermediate trees.

Out of scope for this series, deliberately:

The CMakeLists.txt Boost 1.89.0 build fix and the CI-matrix updates from #205 are not included here. Happy to fold them in (or send a separate PR) if you''d prefer.

Decryption of 6.5.0+ encrypted installers is not implemented. The TSetupEncryptionHeader is parsed and validated, but EncryptionUse != euNone produces a warning and the file body is not decoded.

Dark-mode wizard images (6.6.0+) and the dark variant of the 6.7.0 back-image group are read for stream alignment but not surfaced beyond the new info::wizard_images_back vector for the non-dark 6.7.0 group.

For transparency: #205 by @pelya is a parallel in-flight attempt at the same scope, also still in draft. This series was developed independently; I used #205 only as a confirmation reference for which Inno Setup version first touched which field, not as a source to copy from. There are several deliberate divergences from #205 worth being aware of when you compare them, namely the password.type clearing for 6.5.0+, the native 64-bit consumption in the loader-v2 and block paths rather than truncation back to 32-bit, the discard_padding_to(8) helper instead of hard-coded padding reads, the < 6.4.3 gate (rather than < 6.5.0) for the TSetupFileLocationEntry cleanup based on issrc commits 6aec0a55 and 00d335b7 first appearing at is-6_4_3, the dedicated issig_key_entry data structure rather than skip-only handling, and the reuse of the existing file_entry::checksum field for the per-file ISSig digest. I''m happy to coordinate with @pelya if you''d rather take one branch as the basis and have the other rebased on top.

dscho added 11 commits May 5, 2026 01:13
Inno Setup 6.5.0 bumped SetupLdrOffsetTableVersion from 1 to 2 and
widened the on-disk TSetupLdrOffsetTable struct: TotalSize, OffsetEXE,
Offset0 and Offset1 each grew from 32-bit LongWord to Int64, and a
new ReservedPadding UInt32 was inserted before TableCRC. The record
also lost its `packed` qualifier, but with 32-bit Delphi default
alignment (Int64 is 4-byte aligned in 32-bit Delphi) the on-disk
layout remains contiguous, growing from 48 to 64 bytes total. See
Projects/Src/Shared.Struct.pas at tag is-6_5_0 in
https://github.com/jrsoftware/issrc.

Without this, every installer produced by Inno Setup 6.5.0 or newer
fails to load with:

    Warning: Unexpected setup loader revision: 2
    Warning: Setup loader checksum mismatch!
    Could not determine setup data version!

Detect revision 2 specifically and parse the new layout. The fields
that innoextract actually consumes (exe_offset, header_offset,
data_offset) are still stored as 32-bit in the offsets struct, so
truncate the read 64-bit values to 32-bit and emit a warning if any
of them exceed 4 GiB. Real installers that large are rare in the
wild but possible, and widening the struct is left for a follow-up.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.4.2 added the new [Setup] section directive
CloseApplicationsFilterExcludes (see
https://jrsoftware.org/files/is6.4-whatsnew.htm). It is serialised as a
binary string immediately after architectures_installed_in_64bit_mode_expr
in TSetupHeader (Projects/Src/Shared.Struct.pas in
https://github.com/jrsoftware/issrc at tag is-6_4_2). Read it as a new
header field for installers from 6.4.2 onward; clear it for older
installers.

6.4.2 also bumped the SetupID magic to 'Inno Setup Setup Data (6.4.2)';
6.4.3 to 'Inno Setup Setup Data (6.4.3)'. Both versions are otherwise
on-disk-compatible with the post-6.4.2 layout, so add them to the known
versions table without further parsing changes.

This change is sourced from the prior-art PR dscharrer#202 by itai-delphos
(dscharrer#202), which I am picking
up and extending to cover Inno Setup 6.5.x, 6.6.x and 6.7.x in the
follow-up commits in this series.

Helped-by: itai-delphos@github
Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.5.0 made two on-disk changes to TSetupHeader:

  - A new SevenZipLibraryName: String, serialised right after
    CloseApplicationsFilterExcludes (Projects/Src/Shared.Struct.pas
    at tag is-6_5_0 in https://github.com/jrsoftware/issrc).
  - A new NumISSigKeyEntries: Integer entry-count field, slotted
    between NumDirEntries and NumFileEntries. ISSig (Inno Setup
    Signature) key entries are part of the new ECDSA P-256 ISSigTool
    technology preview added in 6.4.3 and turned into a serialised
    table in 6.5.0. innoextract does not yet process the entries
    themselves; for now consume the count so that NumFileEntries and
    every entry count after it remains aligned.

6.5.0 also bumped the SetupLdrOffsetTableVersion from 1 to 2 and
widened the offset table; that part is handled in the previous
"loader: support setup loader offset table revision 2" commit.

Add SetupID magic strings:
  - 6.5.0 covers 6.5.0 and 6.5.1, which share `Inno Setup Setup Data
    (6.5.0)`.
  - 6.5.2 covers 6.5.2, 6.5.3 and 6.5.4, which share
    `Inno Setup Setup Data (6.5.2)`. The header changes (new wizard
    image background colours and dynamic-dark-mode variants) are added
    in a separate follow-up commit since they are not in the same
    on-disk position as the older WizardImageBackColor field, so they
    require a different branch in `header::load`.

This change continues the prior-art line started by PR dscharrer#202
(dscharrer#202) by itai-delphos.

Helped-by: itai-delphos@github
Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.6.0 made several rearrangements in TSetupHeader's wizard
section (Projects/Src/Shared.Struct.pas at tag is-6_6_0 in
https://github.com/jrsoftware/issrc):

  - Removed WizardStyle. The classic/modern toggle was always going to
    end up as ModernStyle for any installer reaching modern Inno Setup
    versions, so 6.6.0 dropped the field on disk entirely.
  - Added WizardDarkStyle: TSetupWizardDarkStyle (light / dark /
    dynamic), serialised AFTER the WizardSizePercentX/Y pair instead
    of where WizardStyle used to sit.
  - Added WizardImageBackColorDynamicDark and
    WizardSmallImageBackColorDynamicDark, the dark-mode counterparts
    of the colours added back in 6.5.2.

6.6.1 then added one more field at the same position:

  - WizardImageOpacity: Byte. Defaults to 0xff (fully opaque) for
    older installers.

In innoextract these changes are not purely additive: the wizard read
block has to take a 6.6.0+ branch that omits the WizardStyle byte,
and the new colour and opacity fields land between the old
WizardImageAlphaFormat and the rest of the wizard scalars. Add a
stored_dark_style enum mapping (analogous to stored_setup_style),
declare it as a NAMED_ENUM and provide its NAMES so that
stored_enum<>::get()'s warning path can reference its name at compile
time, and add new header fields image_back_color_dynamic_dark,
small_image_back_color_dynamic_dark and wizard_image_opacity.

TSetupHeaderOption itself was reshuffled at the same time. The
shWizardResizable bit was removed (the new modern wizard is always
resizable, so the flag became redundant) and four new wizard-styling
bits were appended at the same position: shWizardModern,
shWizardBorderStyled, shWizardKeepAspectRatio and
shWizardLightButtonsUnstyled. Mirror this in header::flags by adding
the four new enum values, gating the existing WizardResizable add to
``< 6.6.0`` and adding the four new flags for ``>= 6.6.0`` so that
the on-disk bit positions stay aligned. Provide NAMES strings for the
new flags. shWizardLightButtonsUnstyled is later dropped again in
6.7.0; that gate is added in the 6.7.0 patch so that this commit
remains self-contained for installers compiled with 6.6.0 or 6.6.1.

Add the SetupID magic strings 'Inno Setup Setup Data (6.6.0)' and
'Inno Setup Setup Data (6.6.1)'. (Each 6.6.x point release carries a
distinct magic, unlike 6.5.0/.1 and 6.5.2/.3/.4.)

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.7.0 widens several on-disk size and offset fields from
32 to 64 bits (TSetupLdrOffsetTable.OffsetEXE/Offset0/Offset1, the
block-header stored_size, and the new "idskb32" disk-slice header), to
allow setup binaries larger than 4 GiB. The current "loader: support
setup loader offset table revision 2" code path already reads the
widened TSetupLdrOffsetTable fields as Int64, but truncates them back
to 32 bits with a warning when storing into `loader::offsets` because
the struct still holds them in `boost::uint32_t`.

Widen the affected types now, ahead of consuming the new on-disk
formats, so that the follow-up commit can drop the truncations and
read the wider on-disk fields natively without churn in the call
sites. The fields touched are:

  - `loader::offsets::{exe_offset, exe_compressed_size,
    exe_uncompressed_size, message_offset, header_offset,
    data_offset}` and the matching argument of `load_offsets_at`.
  - `stream::chunk::{sort_offset, offset}` (chunk byte offsets within
    a slice; `size` was already 64-bit).
  - `stream::slice_reader::{data_offset, slice_size}`, the matching
    argument of the embedded-data constructor, and the offset
    parameter of `seek(slice, offset)`. The local `read_pos`/
    `remaining` in `slice_reader::read` follow `slice_size`.
  - `cli/extract.cpp`'s local `sort_offset` mirror of
    `chunk::sort_offset`.

The on-disk reads themselves are unchanged: every site still pulls in
the same number of bytes as before, just into wider locals or members,
and the existing `boost::uint32_t(...)` truncation in the loader-v2
path remains in place so behaviour is bit-identical for installers up
to 4 GiB. Where `streampos` / `seekg(off_t)` interactions now produce
unsigned-to-signed warnings on the wider integers, wrap with
`std::streamoff(...)` to keep the conversion explicit and silent.

A follow-up commit drops the loader-v2 truncation and the
"exceeds 4 GiB" warning so installers above the legacy limit are
parsed natively; another follow-up reads the new 64-bit
block-header `stored_size` for Inno Setup 6.7.0 and later.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Now that loader::offsets, stream::chunk, stream::slice_reader and the
block-reader local size hold their values in uint64_t, drop the
truncating uint32_t casts that the previous "loader: support setup
loader offset table revision 2" commit had to use as a placeholder.
The loader-revision-2 path stores the full 64-bit OffsetEXE / Offset0
/ Offset1 directly, and the warning about offsets exceeding 4 GiB is
gone because there is no longer any truncation happening; only a
much narrower sanity check for negative values remains, since the
on-disk fields are signed Int64 in Inno Setup's struct.

stream/block.cpp grows a 6.7.0+ branch in block_reader::get that
loads stored_size as uint64_t to match the on-disk widening
introduced in Inno Setup 6.7.0 (TSetupLdrCompressedBlockHeader's
StoredSize was bumped from LongWord to Int64 in
Projects/Src/Stream.BlockReader.pas at tag is-6_7_0 in
https://github.com/jrsoftware/issrc). With the local stored_size
already widened by the previous refactor, the rest of block_reader
needs no change: the boost::iostreams::restrict slice still receives
the value unchanged via std::streamoff, and the per-4 KiB-subblock
checksum-overhead arithmetic now operates on uint64_t directly so
the explicit uint32_t cast falls away.

Without this commit we observed `block header CRC32 mismatch` on
6.7.0 installers because the older code read just 4 bytes of a
freshly-widened 8-byte StoredSize and then mistook the next 4 bytes
(actually the upper half of StoredSize) for the compressed flag and
the trailing CRC, causing the actual_checksum.finalize() check to
fail. The mismatch is what motivated the type-widening refactor in
the previous commit.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.7.0 padded both TSetupHeaderOption and TSetupFileEntryOption
to 57 elements (foUnusedPadding/shUnusedPadding = 56) so that the
serialised `packed set` always occupies 8 bytes regardless of how many
flags are actually defined. The motivation in issrc is to keep 32-bit
and 64-bit Delphi builds bit-compatible: a `set` with more than 32
flags has a minimum size of 8 bytes in 64-bit Delphi, so 32-bit
builds need to match by reserving the same width.

innoextract reads bitsets through stored_flag_reader<>, which sizes
itself to the number of flags the caller adds. To support the new
padding without exposing the internal byte counter or duplicating the
reader API, add a small public helper that drains additional
padding bytes from the stream until at least `target` bytes have been
consumed in total. A bytes_consumed() getter is added too so callers
can introspect the count if needed.

The follow-up commits that bring innoextract up to Inno Setup 6.7.0
use this from header::load_flags and file_entry::load.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.5.0 made several invasive changes to the on-disk
serialisation that go well beyond the SetupID magic and the new
SevenZipLibraryName header field that the previous patch picked up. To
actually parse a 6.5.0 installer, four further changes are needed.

First, a new TSetupEncryptionHeader record now sits on the outer
stream, between the version magic and the first compressed block
(Projects/Src/Shared.Struct.pas at tag is-6_5_0 in
https://github.com/jrsoftware/issrc). It carries a 4-byte expected
CRC32, a 1-byte EncryptionUse flag, a 16-byte KDFSalt, the KDF
iteration count, the 24-byte BaseNonce triple
(RandomXorStartOffset / RandomXorFirstSlice / RemainingRandom) and a
4-byte PasswordTest, with the CRC32 covering the 49 bytes after
itself. Read it on the outer stream so the block reader starts at the
right offset; if the EncryptionUse byte is non-zero, log a warning
that decrypting 6.5.0+ encrypted installers is not yet supported.
Validate the CRC32 against expected_crc and warn on mismatch.

Second, the matching encryption fields move out of TSetupHeader. The
4-byte SHA-256 digest prefix and the 44-byte salt-plus-nonce blob that
6.4.0 added directly to the header are no longer present in 6.5.0; the
shEncryptionUsed flag is also dropped from TSetupHeaderOption. Gate
the existing 6.4.x reads to ``< 6.5.0`` and clear the
header.password / password_salt members for 6.5.0+ so that downstream
code sees the same "no embedded password" state.

Third, the new TSetupISSigKeyEntry array sits between the directory
and file entry streams. Read NumISSigKeyEntries (already wired up by
the 6.5.0 magic patch as a placeholder, now actually stored in the
new header.issig_key_count). After the directory entries, load
exactly that many records via the standard load_entries helper,
mirroring how component_entry, task_entry, etc. are handled. Each
record holds three binary strings (PublicX, PublicY, RuntimeID)
naming an Ed25519 public key the installer trusts; the new
issig_key_entry struct exposes them so callers that opt in via the
ISSigKeys entry-type flag can inspect them.

Fourth, when a 6.5.0+ installer sets [Setup] SevenZipLibraryName
(supporting Extract7ZipArchive that was added in 6.4.0), an additional
binary string appears on the wizard / decompressor stream after the
decompressor DLL and before the decryptor DLL slot. Skip past it so
later reads of decrypt_dll align correctly.

In TSetupFileEntry, 6.5.0 appended five new expression strings
(Excludes, DownloadISSigSource, DownloadUserName, DownloadPassword,
ExtractArchivePassword) and a per-file Verification packed record
made of an ISSigAllowedKeys ansi string, a 32-byte SHA-256 digest, and
a TSetupFileVerificationType byte enum (none / hash / IS sig); these
sit between BeforeInstall and MinVersion. Two new flag bits
foDownload and foExtractArchive were added to TSetupFileEntryOption
for the new [Files] flags `download` and `extractarchive`. Add the
matching members and stored_enum mapping, gated to `>= 6.5.0`. The
SHA-256 digest is stored in the existing file_entry::checksum field
(unused before 6.5.0 in upstream innoextract); the trailing
unconditional reset of that field is gated to `< 6.5.0` so the
verification hash survives.

In TSetupFileLocationEntry, Inno Setup 6.4.3 (issrc commits 6aec0a55
"Distinguish file options (fo) and file location options (flo)." and
00d335b7 "Cleanup: TSetupFileLocationEntry contained a few things
which Setup doesn't need and are only for the compiler.", both first
tagged in is-6_4_3) had already dropped four flags
(foVersionInfoNotValid, foIsUninstExe, foApplyTouchDateTime,
foSolidBreak) from the Flags bitset and removed the standalone Sign
field entirely; the [Files] `signonce` and `signcheck` directives
still record a per-file location signing intent at compile time but
the result is no longer serialised. Gate the four obsolete flag adds
to `< 6.4.3` and short-circuit the Sign read for `>= 6.4.3` to
NoSetting.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
…tup 6.5.2

Inno Setup 6.5.2 widened TSetupFileLocationEntry.StartOffset from
LongWord (4 bytes) to Int64 (8 bytes) in
Projects/Src/Shared.Struct.pas (tag is-6_5_2 in
https://github.com/jrsoftware/issrc), so that the data offset within
a slice can exceed 4 GiB. The matching change for chunk.first_slice
and chunk.last_slice had already happened in 4.0.0 / 5.x; only
StartOffset was still 32-bit.

Read the new layout as uint64 for `>= 6.5.2`, keep the old 32-bit
read for everything below. The earlier offsets-table widening
patch already widened chunk_location::offset itself to 64 bits, so
the only thing that needed to change here is the read width.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.6.0 reorganised TSetupLanguageEntry beyond what is
already covered by the matching SetupID magic patch. To actually parse
6.6.0 language entries, the on-disk layout in
Projects/Src/Shared.Struct.pas (tag is-6_6_0 in
https://github.com/jrsoftware/issrc) needs three changes.

The TitleFontName and CopyrightFontName binary strings were dropped
entirely (the new dialog-font-base-scale machinery makes per-language
title/copyright fonts unnecessary). The matching TitleFontSize and
CopyrightFontSize integers were replaced by
DialogFontBaseScaleHeight and DialogFontBaseScaleWidth, sitting
between DialogFontSize and WelcomeFontSize. And LanguageID narrowed
from Cardinal (4 bytes) to Word (2 bytes) on disk, since the upper
half was always zero anyway. Add corresponding members for the new
scale fields, gate the obsolete reads to ``< 6.6.0``, and read
LanguageID at the right width.

In TSetupCustomMessageEntry/TSetupPermissionEntry the read order is
unchanged; only the wizard-and-decompressor stream gains material:
6.6.0 added a second copy of each wizard image group right after the
existing main and small image groups, holding the dynamic-dark images
that match the new WantWizardImagesDynamicDark plumbing in
Setup.MainFunc.pas (tag is-6_6_0). Both groups are always serialised
even when dark-mode imagery is not configured; the runtime is what
picks which set to display. innoextract does not expose dark-theme
images yet, but the bytes have to be consumed so the decompressor /
decryptor blocks that follow stay aligned. Read both groups into
local vectors and discard them, gated to ``>= 6.6.0``.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Inno Setup 6.7.0 made another sweep of changes to the on-disk
serialisation. The 6.7.x point releases share a single SetupID magic,
"Inno Setup Setup Data (6.7.0)" (Projects/Src/Setup.MainFunc.pas at
tag is-6_7_0 in https://github.com/jrsoftware/issrc), so 6.7.0 and
6.7.1 are detected together and parsed identically.

In TSetupHeader, the five shUsePrevious* flags
(UsePreviousAppDir, UsePreviousGroup, UsePreviousSetupType,
UsePreviousTasks, UsePreviousUserInfo) were promoted out of the
TSetupHeaderOption bitset into expression-string fields of the same
names, so that they can take per-install conditional values rather
than just on/off. Read the five new strings between
SevenZipLibraryName and LicenseText, and gate the corresponding flag
adds in load_flags to ``< 6.7.0`` so the bitset matches the new
length on the wire.

Three more wizard-colour fields were added next to the 6.5.2/6.6.0
ones: WizardBackColor between WizardSmallImageBackColor and the
*DynamicDark colour pair, WizardBackColorDynamicDark in the same
position relative to the dynamic-dark companions, and
WizardBackImageOpacity (Byte) right after WizardImageOpacity.
TSetupWizardLightControlStyling (wcsAll, wcsAllButButtons,
wcsOnlyRequired) is also stored as a byte enum at that point. Add
header members for all four, default the older versions to 0xff /
LightControlStyleAll respectively, and provide the matching
stored_enum and NAMES blocks.

TSetupHeaderOption itself dropped shWizardLightButtonsUnstyled (the
6.6.x experiment for light theme) and added shRedirectionGuard and
shWizardBevelsHidden at the end. Tighten the existing
WizardLightButtonsUnstyled add to ``< 6.7.0`` and add the two new
flags for ``>= 6.7.0`` with their NAMES strings, mirroring the
6.6.0 pattern. The whole bitset was also padded to 57 elements via
shUnusedPadding=56 so the serialised set is always 8 bytes regardless
of which subset of flags is actually defined. The motivation in
issrc is bit-compatibility between 32-bit and 64-bit Delphi builds
(a `set` with more than 32 elements has a minimum size of 8 bytes in
64-bit Delphi). With every active 6.7.0 header flag now modelled, the
flagreader fills 6 bytes; use the new storedenum helper to drain the
remaining 2 padding bytes up to 8 bytes total. The same pattern
applies to TSetupFileEntryOption with its foUnusedPadding=56
sentinel; add the matching discard_padding_to(8) call after
file_entry's flagreader.finalize().

In TSetupComponentEntry and TSetupTaskEntry, Level narrowed from
Integer (4 bytes) to Byte (1 byte). Both fields were already
restricted to 0..99 in the compiler, so the storage shrink is purely
a wire-format change.

Finally Setup.MainFunc.pas adds a third wizard image group on the
wizard / decompressor stream for the new WizardBackImageFile
directive, in addition to the existing main and small image groups.
The same group is duplicated for the dynamic-dark theme that 6.6.0
introduced, matching the existing main/small dark pair. Read the new
non-dark group into a new info::wizard_images_back vector (so
extraction can later expose it), and read the dark back-image group
into a discarded local. Both are gated to ``>= 6.7.0`` and sit on
exactly the same fork between the two pre-existing groups and the
decompressor DLL block as the 6.6.0 dynamic-dark groups.

Assisted-by: Claude Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho dscho marked this pull request as ready for review May 11, 2026 11:35
dscho added a commit to dscho/MINGW-packages that referenced this pull request May 15, 2026
Recent Git for Windows installers are built with Inno Setup 6.7.x, and
the currently-packaged innoextract bails out on the SetupID magic for
any Inno Setup version newer than 6.4.1. That is a concrete regression
for users who rely on innoextract to inspect or unpack Git for Windows
installers, and presumably other installers built with current Inno
Setup releases.

To address that, dscharrer/innoextract#210 adds
on-disk format support for Inno Setup 6.4.2, 6.4.3, 6.5.0 through 6.5.4,
6.6.0, 6.6.1, 6.7.0, and 6.7.1, in 11 commits on top of the upstream
dscharrer/innoextract master tip. That PR is currently a draft upstream.

Rather than pointing _commit at a personal fork carrying those commits,
keep this package close to upstream: _commit stays pinned to the
upstream tip, the 11 commits are exported via git format-patch and
applied in prepare() with a patch -Np1 loop, and only pkgrel is bumped.
Once dscharrer/innoextract#210 is merged, the patches can be dropped
and _commit re-pinned to a commit that already contains them.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
lazka pushed a commit to msys2/MINGW-packages that referenced this pull request May 18, 2026
Recent Git for Windows installers are built with Inno Setup 6.7.x, and
the currently-packaged innoextract bails out on the SetupID magic for
any Inno Setup version newer than 6.4.1. That is a concrete regression
for users who rely on innoextract to inspect or unpack Git for Windows
installers, and presumably other installers built with current Inno
Setup releases.

To address that, dscharrer/innoextract#210 adds
on-disk format support for Inno Setup 6.4.2, 6.4.3, 6.5.0 through 6.5.4,
6.6.0, 6.6.1, 6.7.0, and 6.7.1, in 11 commits on top of the upstream
dscharrer/innoextract master tip. That PR is currently a draft upstream.

Rather than pointing _commit at a personal fork carrying those commits,
keep this package close to upstream: _commit stays pinned to the
upstream tip, the 11 commits are exported via git format-patch and
applied in prepare() with a patch -Np1 loop, and only pkgrel is bumped.
Once dscharrer/innoextract#210 is merged, the patches can be dropped
and _commit re-pinned to a commit that already contains them.

Assisted-by: Opus 4.7

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant