installer: actually build a 64-bit installer - #732
Merged
Merged
Conversation
1 task
dennisameling
commented
Aug 25, 2026
Comment on lines
+56
to
+61
| #if BITNESS=='64' && Ver>=EncodeVer(7, 0, 0) | ||
| ; Inno Setup 7 builds 32-bit installers unless told otherwise. SETUP_IS_X64 | ||
| ; lets the Pascal Script code declare Windows API records for 64-bit. | ||
| #define SETUP_IS_X64 | ||
| SetupArchitecture=x64 | ||
| #endif |
Member
Author
There was a problem hiding this comment.
As a follow-up, we'll probably want to remove all 32-bit / x86-related code from the installer, given that it's no longer supported (except for MinGit which doesn't use this installer).
This was referenced Aug 28, 2026
dscho
approved these changes
Aug 28, 2026
dscho
reviewed
Aug 31, 2026
| #ifdef SETUP_IS_X64 | ||
| timePadding:DWORD; | ||
| #endif | ||
| pt:TPoint; |
Member
There was a problem hiding this comment.
Ah, there is a tiny problem here (will fix in a moment): TPoint does not need to be 8-byte aligned, apparently:
#include <stdio.h>
#include <windows.h>
int main(int argc, char **argv)
{
MSG msg;
#define P(name) printf("offset of " #name ": 0x%02x\n", (int)((char *)&msg. name - (char *)&msg))
P(hwnd);
P(message);
P(wParam);
P(lParam);
P(time);
P(pt);
printf("offset of lPrivate: 0x%02x\n", (int)((char *)&msg.pt - (char *)&msg) + sizeof(msg.pt));
return 0;
}prints
offset of hwnd: 0x00
offset of message: 0x08
offset of wParam: 0x10
offset of lParam: 0x18
offset of time: 0x20
offset of pt: 0x24
offset of lPrivate: 0x2c
And this test InnoSetup program with the adjusted definition agrees:
[Setup]
AppName=MSG Layout Probe
AppVersion=1
DefaultDirName={tmp}\MsgProbe
OutputBaseFilename=msg-probe
SetupArchitecture=x64
Uninstallable=no
[Code]
type
TByteArray = array of Byte;
TMsg = record
hwnd:HWND;
message:UINT;
messagePadding:DWORD;
wParam:ULONG_PTR;
lParam:ULONG_PTR;
time:DWORD;
pt:TPoint;
lPrivate:DWORD;
end;
procedure RtlMoveMemory(var Destination: TMsg; Source: TByteArray; Length: SIZE_T);
external 'RtlMoveMemory@kernel32.dll stdcall';
function InitializeSetup: Boolean;
var
Bytes: TByteArray;
Info: TMsg;
I: Integer;
begin
SetArrayLength(Bytes, 48);
for I := 0 to GetArrayLength(Bytes) - 1 do
Bytes[I] := 0;
Bytes[$00] := 1;
Bytes[$08] := 2;
Bytes[$10] := 3;
Bytes[$18] := 4;
Bytes[$20] := 5;
Bytes[$24] := 6;
Bytes[$28] := 7;
Bytes[$2c] := 8;
RtlMoveMemory(Info, Bytes, SizeOf(Info));
Log('SizeOf=' + IntToStr(SizeOf(Info)));
Log('hwnd=' + UIntToStr(Info.hwnd));
Log('message=' + UIntToStr(Info.message));
Log('wParam=' + UIntToStr(Info.wParam));
Log('lParam=' + UIntToStr(Info.lParam));
Log('time=' + UIntToStr(Info.time));
Log('pt.x=' + UIntToStr(Info.pt.x));
Log('pt.y=' + UIntToStr(Info.pt.y));
Log('lPrivate=' + UIntToStr(Info.lPrivate));
Result := False;
end;Output:
2026-08-31 13:04:05.040 SizeOf=48
2026-08-31 13:04:05.040 hwnd=1
2026-08-31 13:04:05.040 message=2
2026-08-31 13:04:05.040 wParam=3
2026-08-31 13:04:05.040 lParam=4
2026-08-31 13:04:05.040 time=5
2026-08-31 13:04:05.040 pt.x=6
2026-08-31 13:04:05.040 pt.y=7
2026-08-31 13:04:05.040 lPrivate=8
Inno Setup 7 introduced 64-bit installers, but building 32-bit ones stays the default in both editions; a 64-bit one is only produced when the `[Setup]` section directive `SetupArchitecture` is set to `x64`. Updating the compiler to Inno Setup 7.0.2 therefore did not change the architecture of the installer, even though the v2.55.0(5) release notes already announced it as a 64-bit executable. Set `SetupArchitecture=x64` for the flavors that ship 64-bit Git, i.e. the ones where `release.sh` sets `BITNESS` to 64: MINGW64, UCRT64 and CLANGARM64. The i686 installer keeps building as a 32-bit executable. The directive does not exist in Inno Setup 6, hence the version guard. Flipping that directive alone leaves the installer broken, though: Pascal Script records are always packed, and in a 64-bit installer pointers are eight bytes wide, so the Windows API records declared in `exec-with-capture.inc.iss` no longer match the layout those functions expect. `CreatePipe()` reads `lpSecurityDescriptor` from the wrong offset, fails with `ERROR_NOACCESS`, and `ExecWithCapture()` returns `False` without ever having run the command. Starting the wizard then greets the user with Unable to get system config (exit code 4294967295): Widen the pointer-sized fields of `SECURITY_ATTRIBUTES` and `STARTUPINFO` to `ULONG_PTR` and add the padding that the aligned C structs have and a packed record does not, which brings them to the 24 and 104 bytes that the x64 ABI mandates. `MSG` needs the same treatment for a different reason: `PeekMessage()` writes the full 48 bytes of that struct, which is more than an unpadded record offers, corrupting the stack and killing the message pump with a fatal exception once a captured command runs long enough for the pump to kick in. The padding is conditional on the new `SETUP_IS_X64` symbol, so 32-bit installers keep the record layout they have always had. The `Win95` and `Win2000` code paths in `modules.inc.iss` declare records with the same problem (`PROCESSENTRY32`, `MODULEENTRY32`), but `MinVersion` is 6.3 and those paths are only taken on Windows versions before Vista, so they are left alone. This fixes git-for-windows/git#6372. Signed-off-by: Dennis Ameling <dennis@dennisameling.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
dscho
force-pushed
the
64-bit-installer
branch
from
August 31, 2026 11:08
418b9e3 to
0dee1bc
Compare
Member
|
For the record, I inspected the other |
github-actions Bot
pushed a commit
that referenced
this pull request
Aug 31, 2026
The installer [is now _actually_ a 64-bit one](#732), which fixes the problem that [the external OpenSSH option was broken in Git for Windows v2.55.0(5)](git-for-windows/git#6374). Signed-off-by: gitforwindowshelper[bot] <gitforwindowshelper-bot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This fixes git-for-windows/git#6372.
Confirming that the installer is now truly a x64 executable:
Inno Setup 7 introduced 64-bit installers, but building 32-bit ones stays the default in both editions; a 64-bit one is only produced when the
[Setup]section directiveSetupArchitectureis set tox64. Updating the compiler to Inno Setup 7.0.2 therefore did not change the architecture of the installer, even though the v2.55.0(5) release notes already announced it as a 64-bit executable.Set
SetupArchitecture=x64for the flavors that ship 64-bit Git, i.e. the ones whererelease.shsetsBITNESSto 64: MINGW64, UCRT64 and CLANGARM64. The i686 installer keeps building as a 32-bit executable. The directive does not exist in Inno Setup 6, hence the version guard.Flipping that directive alone leaves the installer broken, though: Pascal Script records are always packed, and in a 64-bit installer pointers are eight bytes wide, so the Windows API records declared in
exec-with-capture.inc.issno longer match the layout those functions expect.CreatePipe()readslpSecurityDescriptorfrom the wrong offset, fails withERROR_NOACCESS, andExecWithCapture()returnsFalsewithout ever having run the command. Starting the wizard then greets the user withWiden the pointer-sized fields of
SECURITY_ATTRIBUTESandSTARTUPINFOtoULONG_PTRand add the padding that the aligned C structs have and a packed record does not, which brings them to the 24 and 104 bytes that the x64 ABI mandates.MSGneeds the same treatment for a different reason:PeekMessage()writes the full 48 bytes of that struct, which is more than an unpadded record offers, corrupting the stack and killing the message pump with a fatal exception once a captured command runs long enough for the pump to kick in.The padding is conditional on the new
SETUP_IS_X64symbol, so 32-bit installers keep the record layout they have always had.The
Win95andWin2000code paths inmodules.inc.issdeclare records with the same problem (PROCESSENTRY32,MODULEENTRY32), butMinVersionis 6.3 and those paths are only taken on Windows versions before Vista, so they are left alone.