瀏覽代碼

Merge branch 'x64compatible' (without changes)

Martijn Laan 1 年之前
父節點
當前提交
13b7e3c570

+ 9 - 8
Examples/64Bit.iss

@@ -2,7 +2,7 @@
 ; Demonstrates installation of a program built for the x64 (a.k.a. AMD64)
 ; architecture.
 ; To successfully run this installation and the program it installs,
-; you must have a "x64" edition of Windows.
+; you must have a "x64" edition of Windows or Windows 11 on Arm.
 
 ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES!
 
@@ -16,13 +16,14 @@ UninstallDisplayIcon={app}\MyProg.exe
 Compression=lzma2
 SolidCompression=yes
 OutputDir=userdocs:Inno Setup Examples Output
-; "ArchitecturesAllowed=x64" specifies that Setup cannot run on
-; anything but x64.
-ArchitecturesAllowed=x64
-; "ArchitecturesInstallIn64BitMode=x64" requests that the install be
-; done in "64-bit mode" on x64, meaning it should use the native
-; 64-bit Program Files directory and the 64-bit view of the registry.
-ArchitecturesInstallIn64BitMode=x64
+; "ArchitecturesAllowed=x64compatible" specifies that Setup cannot run
+; on anything but x64 and Windows 11 on Arm.
+ArchitecturesAllowed=x64compatible
+; "ArchitecturesInstallIn64BitMode=x64compatible" requests that the
+; install be done in "64-bit mode" on x64 or Windows 11 on Arm,
+; meaning it should use the native 64-bit Program Files directory and
+; the 64-bit view of the registry.
+ArchitecturesInstallIn64BitMode=x64compatible
 
 [Files]
 Source: "MyProg-x64.exe"; DestDir: "{app}"; DestName: "MyProg.exe"

+ 32 - 21
Examples/64BitThreeArch.iss

@@ -1,6 +1,6 @@
 ; -- 64BitThreeArch.iss --
 ; Demonstrates how to install a program built for three different
-; architectures (x86, x64, ARM64) using a single installer.
+; architectures (x86, x64, Arm64) using a single installer.
 
 ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES!
 
@@ -14,22 +14,33 @@ UninstallDisplayIcon={app}\MyProg.exe
 Compression=lzma2
 SolidCompression=yes
 OutputDir=userdocs:Inno Setup Examples Output
-; "ArchitecturesInstallIn64BitMode=x64 arm64" requests that the install
-; be done in "64-bit mode" on x64 & ARM64, meaning it should use the
-; native 64-bit Program Files directory and the 64-bit view of the
-; registry. On all other architectures it will install in "32-bit mode".
-ArchitecturesInstallIn64BitMode=x64 arm64
+; "ArchitecturesInstallIn64BitMode=x64compatible arm64" instructs
+; Setup to use "64-bit install mode" on x64-compatible systems and
+; Arm64 systems, meaning Setup should use the native 64-bit Program
+; Files directory and the 64-bit view of the registry. On all other
+; OS architectures (e.g., 32-bit x86), Setup will use "32-bit
+; install mode".
+ArchitecturesInstallIn64BitMode=x64compatible or arm64
 
 [Files]
-; Install MyProg-x64.exe if running on x64, MyProg-ARM64.exe if
-; running on ARM64, MyProg.exe otherwise.
-; Place all x64 files here
-Source: "MyProg-x64.exe"; DestDir: "{app}"; DestName: "MyProg.exe"; Check: InstallX64
-; Place all ARM64 files here, first one should be marked 'solidbreak'
-Source: "MyProg-ARM64.exe"; DestDir: "{app}"; DestName: "MyProg.exe"; Check: InstallARM64; Flags: solidbreak
-; Place all x86 files here, first one should be marked 'solidbreak'
-Source: "MyProg.exe"; DestDir: "{app}"; Check: InstallOtherArch; Flags: solidbreak
-; Place all common files here, first one should be marked 'solidbreak'
+; In order of preference, we want to install:
+; - Arm64 binaries on Arm64 systems
+; - else, x64 binaries on x64-compatible systems
+; - else, x86 binaries
+
+; Place all Arm64-specific files here, using 'Check: PreferArm64Files' on each entry.
+Source: "MyProg-Arm64.exe"; DestDir: "{app}"; DestName: "MyProg.exe"; Check: PreferArm64Files
+
+; Place all x64-specific files here, using 'Check: PreferX64Files' on each entry.
+; Only the first entry should include the 'solidbreak' flag.
+Source: "MyProg-x64.exe"; DestDir: "{app}"; DestName: "MyProg.exe"; Check: PreferX64Files; Flags: solidbreak
+
+; Place all x86-specific files here, using 'Check: PreferX86Files' on each entry.
+; Only the first entry should include the 'solidbreak' flag.
+Source: "MyProg.exe"; DestDir: "{app}"; Check: PreferX86Files; Flags: solidbreak
+
+; Place all common files here.
+; Only the first entry should include the 'solidbreak' flag.
 Source: "MyProg.chm"; DestDir: "{app}"; Flags: solidbreak
 Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme
 
@@ -37,17 +48,17 @@ Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme
 Name: "{group}\My Program"; Filename: "{app}\MyProg.exe"
 
 [Code]
-function InstallX64: Boolean;
+function PreferArm64Files: Boolean;
 begin
-  Result := Is64BitInstallMode and (ProcessorArchitecture = paX64);
+  Result := IsArm64;
 end;
 
-function InstallARM64: Boolean;
+function PreferX64Files: Boolean;
 begin
-  Result := Is64BitInstallMode and (ProcessorArchitecture = paARM64);
+  Result := not PreferArm64Files and IsX64Compatible;
 end;
 
-function InstallOtherArch: Boolean;
+function PreferX86Files: Boolean;
 begin
-  Result := not InstallX64 and not InstallARM64;
+  Result := not PreferArm64Files and not PreferX64Files;
 end;

+ 9 - 8
Examples/64BitTwoArch.iss

@@ -2,8 +2,8 @@
 ; Demonstrates how to install a program built for two different
 ; architectures (x86 and x64) using a single installer: on a "x86"
 ; edition of Windows the x86 version of the program will be
-; installed but on a "x64" edition of Windows the x64 version will
-; be installed.
+; installed but on a "x64" edition of Windows or Windows 11 on Arm
+; the x64 version will be installed.
 
 ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES!
 
@@ -17,17 +17,18 @@ WizardStyle=modern
 Compression=lzma2
 SolidCompression=yes
 OutputDir=userdocs:Inno Setup Examples Output
-; "ArchitecturesInstallIn64BitMode=x64" requests that the install be
-; done in "64-bit mode" on x64, meaning it should use the native
-; 64-bit Program Files directory and the 64-bit view of the registry.
+; "ArchitecturesInstallIn64BitMode=x64compatible" requests that the
+; install be done in "64-bit mode" on x64 or Windows 11 on Arm,
+; meaning it should use the native 64-bit Program Files directory and
+; the 64-bit view of the registry.
 ; On all other architectures it will install in "32-bit mode".
-ArchitecturesInstallIn64BitMode=x64
-; Note: We don't set ProcessorsAllowed because we want this
+ArchitecturesInstallIn64BitMode=x64compatible
+; Note: We don't set ArchitecturesAllowed because we want this
 ; installation to run on all architectures (including Itanium,
 ; since it's capable of running 32-bit code too).
 
 [Files]
-; Install MyProg-x64.exe if running in 64-bit mode (x64; see above),
+; Install MyProg-x64.exe if running in 64-bit mode (see above), and
 ; MyProg.exe otherwise.
 ; Place all x64 files here
 Source: "MyProg-x64.exe"; DestDir: "{app}"; DestName: "MyProg.exe"; Check: Is64BitInstallMode

+ 1 - 1
Examples/MyProg/Myprog.c

@@ -6,7 +6,7 @@
 #elif defined(_AMD64_)
 	#define ARCHNOTE TEXT("\n\n(This EXE was compiled for the x64 architecture.)")
 #elif defined(_M_ARM64)
-	#define ARCHNOTE TEXT("\n\n(This EXE was compiled for the ARM64 architecture.)")
+	#define ARCHNOTE TEXT("\n\n(This EXE was compiled for the Arm64 architecture.)")
 #elif defined(_IA64_)
 	#define ARCHNOTE TEXT("\n\n(This EXE was compiled for the Itanium architecture.)")
 #else

+ 119 - 21
ISHelp/isetup.xml

@@ -62,6 +62,7 @@
     <contentstopic title="Non Administrative Install Mode" topic="admininstallmode" />
     <contentstopic title="64-bit Install Mode" topic="32vs64bitinstalls" />
     <contentstopic title="64-bit Installation Limitations" topic="64bitlimitations" />
+    <contentstopic title="Architecture Identifiers" topic="archidentifiers" />
     <contentstopic title="Wizard Pages" topic="wizardpages" />
     <contentstopic title="Installation Order" topic="installorder" />
     <contentstopic title="Unsafe Files" topic="unsafefiles" />
@@ -101,9 +102,9 @@ Inno Setup is a <i>free</i> installer for Windows programs by Jordan Russell and
 
 <ul>
 
-<li>Support for every Windows release since 2009, including: Windows 11, Windows 10, Windows 10 on ARM, Windows Server 2019, Windows Server 2016, Windows 8.1, Windows 8, Windows Server 2012, Windows 7, and Windows Server 2008 R2. (No service packs are required.)</li>
+<li>Support for every Windows release since 2009, including: Windows 11, Windows 10, Windows 11 on Arm, Windows 10 on Arm, Windows Server 2019, Windows Server 2016, Windows 8.1, Windows 8, Windows Server 2012, Windows 7, and Windows Server 2008 R2. (No service packs are required.)</li>
 
-<li>Extensive support for installation of <link topic="32vs64bitinstalls">64-bit</link> applications on the 64-bit editions of Windows. The x64, ARM64 and Itanium architectures are all supported.</li>
+<li>Extensive support for installation of <link topic="32vs64bitinstalls">64-bit</link> applications on the 64-bit editions of Windows. The x64, Arm64 and Itanium architectures are all supported.</li>
 
 <li>Extensive support for both administrative and <link topic="admininstallmode">non administrative installations</link> installations.</li>
 
@@ -852,7 +853,7 @@ For example: If you used <tt>{src}\MYPROG.EXE</tt> on an entry and the user is i
 <param name="Languages">
 <p>A space separated list of language names, telling Setup to which languages the entry belongs. If the end user selects a language from this list, the entry is processed (for example: the file is installed).</p>
 <p>An entry without a <tt>Languages</tt> parameter is always processed, unless other parameters say it shouldn't be.</p>
-<p>Besides space separated lists, you may also use boolean expressions. See <link topic="componentstasksparams">Components and Tasks parameters</link> for examples of boolean expressions.</p>
+<p>Besides space separated lists, you may also use boolean expressions containing language names. See <link topic="componentstasksparams">Components and Tasks parameters</link> for examples of boolean expressions.</p>
 <example>
 <pre>Languages: en nl</pre>
 </example>
@@ -919,7 +920,7 @@ Name: "{commondesktop}\My Program"; Filename: "{app}\MyProg.exe"; Components: ma
 </paramlist>
 
 <p><br/>
-Besides space separated lists, you may also use boolean expressions as Components and Tasks parameters. Supported operators include <tt>not</tt>, <tt>and</tt>, and <tt>or</tt>. For example:</p>
+Besides space separated lists, you may also use boolean expressions containing component or task names as Components and Tasks parameters. Supported operators include <tt>not</tt>, <tt>and</tt>, and <tt>or</tt>. For example:</p>
 
 <precode>
 [Components]
@@ -1735,8 +1736,8 @@ Instructs Setup to proceed to comparing time stamps (last write/modified time) i
 </flag>
 <flag name="regtypelib">
 <p>Register the type library (.tlb). The uninstaller will unregister the type library (unless the flag <tt>uninsneveruninstall</tt> is specified). As with the <tt>regserver</tt> flag, when used in combination with <tt>sharedfile</tt>, the file will only be unregistered by the uninstaller when the reference count reaches zero.</p>
-<p>In <link topic="32vs64bitinstalls">64-bit install mode</link> running on an x64 edition of Windows, the type library will be registered inside a 64-bit process. You can override this by specifying the <tt>32bit</tt> flag.</p>
-<p>Registering type libraries in 64-bit mode on Itanium editions of Windows is not supported.</p>
+<p>In <link topic="32vs64bitinstalls">64-bit install mode</link> running on an x64-compatible edition of Windows, the type library will be registered inside a 64-bit process. You can override this by specifying the <tt>32bit</tt> flag.</p>
+<p>Registering type libraries in 64-bit mode on Itanium editions of Windows or on Windows 10 for Arm is not supported.</p>
 <p>See the <i>Remarks</i> at the bottom of this topic for more information.</p>
 </flag>
 <flag name="replacesameversion">
@@ -2937,9 +2938,9 @@ Shown by default, but can be disabled in some cases via <link topic="setup_disab
 
 <li>If <link topic="setup_restartapplications">RestartApplications</link> was set to <tt>yes</tt>, Setup restarts closed applications which support being restarted.</li>
 
-<li>If <link topic="setup_changesassociations">ChangesAssociations</link> was set to <tt>yes</tt> or to a <link topic="scriptexpression">boolean expression</link> evaluating to <tt>True</tt>, file associations are refreshed now.</li>
+<li>If <link topic="setup_changesassociations">ChangesAssociations</link> was set to <tt>yes</tt> or to a <link topic="scriptexpression">scripted boolean expression</link> evaluating to <tt>True</tt>, file associations are refreshed now.</li>
 
-<li>If <link topic="setup_changesenvironment">ChangesEnvironment</link> was set to <tt>yes</tt> or to a <link topic="scriptexpression">boolean expression</link> evaluating to <tt>True</tt>, other applications are notified at this point.</li>
+<li>If <link topic="setup_changesenvironment">ChangesEnvironment</link> was set to <tt>yes</tt> or to a <link topic="scriptexpression">scripted boolean expression</link> evaluating to <tt>True</tt>, other applications are notified at this point.</li>
 
 </ul>
 
@@ -4063,10 +4064,10 @@ C:\Program Files\My Program
 </setuptopic>
 
 <setuptopic directive="Uninstallable">
-<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">boolean expression</link></setupvalid>
+<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">scripted boolean expression</link></setupvalid>
 <setupdefault><tt>yes</tt></setupdefault>
 <body>
-<p>This determines if Inno Setup's automatic uninstaller is to be included in the installation. If this is <tt>yes</tt> or to a <link topic="scriptexpression">boolean expression</link> evaluating to <tt>True</tt> the uninstaller is included. Otherwise, no uninstallation support is included, requiring the end-user to manually remove the files pertaining to your application.</p>
+<p>This determines if Inno Setup's automatic uninstaller is to be included in the installation. If this is <tt>yes</tt> or to a <link topic="scriptexpression">scripted boolean expression</link> evaluating to <tt>True</tt> the uninstaller is included. Otherwise, no uninstallation support is included, requiring the end-user to manually remove the files pertaining to your application.</p>
 <p>Setting this to a boolean expression can be useful if you want to offer the user a 'portable mode' option.</p>
 <example><pre>[Setup]
 Uninstallable=not IsTaskSelected('portablemode')
@@ -4292,10 +4293,10 @@ Name: portablemode; Description: "Portable Mode"</pre></example>
 </setuptopic>
 
 <setuptopic directive="CreateUninstallRegKey">
-<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">boolean expression</link></setupvalid>
+<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">scripted boolean expression</link></setupvalid>
 <setupdefault><tt>yes</tt></setupdefault>
 <body>
-<p>If this is set to <tt>no</tt> or to a <link topic="scriptexpression">boolean expression</link> evaluating to <tt>False</tt>, Setup won't create an entry in the <i>Add/Remove Programs</i> Control Panel applet.</p>
+<p>If this is set to <tt>no</tt> or to a <link topic="scriptexpression">scripted boolean expression</link> evaluating to <tt>False</tt>, Setup won't create an entry in the <i>Add/Remove Programs</i> Control Panel applet.</p>
 <p>Setting this to <tt>no</tt> can be useful if your installation is merely an update to an existing application and you don't want another entry created, but don't want to the disable the uninstall features entirely (via <tt>Uninstallable=no</tt>). In this case, <link topic="setup_updateuninstalllogappname">UpdateUninstallLogAppName</link> is usually set to <tt>no</tt> as well.</p>
 <p><b>See also:</b><br/>
 <link topic="setup_uninstallable">Uninstallable</link>
@@ -4717,19 +4718,19 @@ DiskSliceSize=1457664
 </setuptopic>
 
 <setuptopic directive="ChangesAssociations">
-<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">boolean expression</link></setupvalid>
+<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">scripted boolean expression</link></setupvalid>
 <setupdefault><tt>no</tt></setupdefault>
 <body>
-<p>When set to <tt>yes</tt> or to a <link topic="scriptexpression">boolean expression</link> evaluating to <tt>True</tt>, Setup will tell Explorer to refresh its file associations information at the end of the installation, and Uninstall will do the same at the end of uninstallation.</p>
+<p>When set to <tt>yes</tt> or to a <link topic="scriptexpression">scripted boolean expression</link> evaluating to <tt>True</tt>, Setup will tell Explorer to refresh its file associations information at the end of the installation, and Uninstall will do the same at the end of uninstallation.</p>
 <p>If your installation creates a file association but doesn't have <tt>ChangesAssociations</tt> set to <tt>yes</tt>, the correct icon for the file type likely won't be displayed until the user logs off or restarts the computer.</p>
 </body>
 </setuptopic>
 
 <setuptopic directive="ChangesEnvironment">
-<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">boolean expression</link></setupvalid>
+<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link>, or a <link topic="scriptexpression">scripted boolean expression</link></setupvalid>
 <setupdefault><tt>no</tt></setupdefault>
 <body>
-<p>When set to <tt>yes</tt> or to a <link topic="scriptexpression">boolean expression</link> evaluating to <tt>True</tt>, at the end of the installation Setup will notify other running applications (notably Windows Explorer) that they should reload their environment variables from the registry.</p>
+<p>When set to <tt>yes</tt> or to a <link topic="scriptexpression">scripted boolean expression</link> evaluating to <tt>True</tt>, at the end of the installation Setup will notify other running applications (notably Windows Explorer) that they should reload their environment variables from the registry.</p>
 <p>If your installation creates or changes an environment variable but doesn't have <tt>ChangesEnvironment</tt> set to <tt>yes</tt>, the new/changed environment variable will not be seen by applications launched from Explorer until the user logs off or restarts the computer.</p>
 </body>
 </setuptopic>
@@ -5235,6 +5236,63 @@ DiskSliceSize=1457664
 </body>
 </setuptopic>
 
+<topic name="archidentifiers" title="Architecture Identifiers">
+<keyword value="Architecture Identifiers" />
+<body>
+
+<p>These are used in the values of <link topic="setup_architecturesallowed">ArchitecturesAllowed</link> and <link topic="setup_architecturesinstallin64bitmode">ArchitecturesInstallIn64BitMode</link>.</p>
+
+<dl>
+
+<dt><b>arm32compatible</b></dt>
+<dd>
+<p>Matches systems capable of running 32-bit Arm binaries. Only Arm64 Windows includes such support.</p>
+</dd>
+
+<dt><b>arm64</b></dt>
+<dd>
+<p>Matches systems running Arm64 Windows.</p>
+</dd>
+
+<dt><b>win64</b></dt>
+<dd>
+<p>Matches systems running 64-bit Windows, regardless of OS architecture.</p>
+<p>This may be useful in an installer that doesn't ship any architecture-specific binaries, but requires access to something 64-bit, like <tt>HKLM64</tt> in the [Registry] section, or the native 64-bit Program Files directory.</p>
+</dd>
+
+<dt><b>x64compatible</b></dt>
+<dd>
+<p>Matches systems capable of running x64 binaries. This includes systems running x64 Windows, and also Arm64-based Windows 11 systems, which have the ability to run x64 binaries via emulation.</p>
+</dd>
+
+<dt><b>x64os</b></dt>
+<dd>
+<p>Matches systems running x64 Windows only — not any other systems that have the ability to run x64 binaries via emulation.</p>
+<p>In most cases, <tt>x64compatible</tt> should be used instead of <tt>x64os</tt>, because <tt>x64compatible</tt> allows x64 apps to be installed on Arm64-based Windows 11 systems as well.</p>
+<p>However, <tt>x64os</tt> is appropriate in unusual cases where an x64 app/binary is known to require true x64 Windows and cannot function under emulation. x64 device drivers are one example; x64 emulation isn't supported in kernel mode.</p>
+<p>Before Inno Setup 6.3, <tt>x64os</tt> was named <tt>x64</tt>. The compiler still accepts <tt>x64</tt> as an alias for <tt>x64os</tt>, but will emit a deprecation warning when used.</p>
+</dd>
+
+<dt><b>x86compatible</b></dt>
+<dd>
+<p>Matches systems capable of running 32-bit x86 binaries. This includes systems running x86 Windows, x64 Windows, and also Arm64-based Windows 10 and 11 systems, which have the ability to run x86 binaries via emulation.</p>
+<p>Given that Setup itself is currently always built as a 32-bit x86 binary, this always matches.</p>
+</dd>
+
+<dt><b>x86os</b></dt>
+<dd>
+<p>Matches systems running 32-bit x86 Windows only.</p>
+<p><tt>x86os</tt> usually only makes sense when installing 32-bit x86 device drivers. When installing a regular 32-bit app, <tt>x86compatible</tt> should be used instead (or just leave <tt>ArchitecturesAllowed</tt> unset).</p>
+<p>Before Inno Setup 6.3, <tt>x86os</tt> was named <tt>x86</tt>. The compiler still accepts <tt>x86</tt> as an alias for <tt>x86os</tt>.</p>
+</dd>
+
+</dl>
+<p><b>See also:</b><br/>
+<link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p>
+</body>
+</topic>
+
 <setuptopic directive="ArchitecturesAllowed">
 <keyword value="processors allowed" />
 <keyword value="x86" />
@@ -5242,14 +5300,46 @@ DiskSliceSize=1457664
 <keyword value="x64" />
 <keyword value="IA-64" />
 <keyword value="Itanium" />
-<keyword value="ARM64" />
-<setupvalid>One or more of the following, separated by spaces: <br/><tt>x86</tt> <br/><tt>x64</tt> <br/><tt>arm64</tt> <br/><tt>ia64</tt></setupvalid>
+<keyword value="Arm64" />
+<setupvalid>A space separated list of <link topic="archidentifiers">architecture identifiers</link>.<br />
+Or, a boolean expression containing <link topic="archidentifiers">architecture identifiers</link>. See <link topic="componentstasksparams">Components and Tasks parameters</link> for examples of boolean expressions.</setupvalid>
 <setupdefault><i>(blank)</i></setupdefault>
 <body>
 <p>Specifies which processor architecture(s) Setup is allowed to run on. If this directive is not specified or is blank, Setup will be allowed to run on all processor architectures capable of executing its 32-bit code (including ones it doesn't recognize). Otherwise, if a user's processor architecture is not one of those specified in this directive, Setup will display an error message and exit.</p>
 <p>If your application's binaries are all 32-bit and run in user mode, you should not change this directive from its default value (specifically, don't set it to <tt>x86</tt>), because normally such binaries will run without issue on the 64-bit Windows via the WOW64 emulator.</p>
 <p>If you install any 32-bit device drivers, you should set this directive to <tt>x86</tt>, as 32-bit device drivers cannot function on 64-bit Windows.</p>
-<p>If your application's binaries are built for the x64, ARM64 or Itanium architectures, you should set this directive to either <tt>x64</tt>, <tt>arm64</tt> or <tt>ia64</tt> respectively.</p>
+<p>If your application's binaries are built for the x64, Arm64 or Itanium architectures, you should set this directive to either <tt>x64compatible</tt>, <tt>arm64</tt> or <tt>ia64</tt> respectively.</p>
+<examples>
+<pre>
+; Only allow installation on systems that aren't x64-compatible.
+; Useful in a situation where you have separate x86 &amp; x64 installers,
+; and don't want users of x64-compatible OSes (x64 + Win11 Arm64)
+; erroneously running the x86 installer which would say:
+ArchitecturesAllowed=not x64compatible
+
+; Require two arch matches at the same time:
+; If an Arm installer installs both Arm64 and Arm32 binaries,
+; you technically should ensure that the OS actually supports both:
+ArchitecturesAllowed=arm64 and arm32compatible
+
+; Same goes for an x64-compatible installer shipping some 32-bit
+; binaries:
+ArchitecturesAllowed=x64compatible and x86compatible
+
+; Installing a component that cannot operate in an emulated
+; environment, such as an x64 device driver:
+ArchitecturesAllowed=x64os
+
+; Allow installation on x64-compatible systems, but deny one of them:
+; (Imagine if in the future there were 3 x64-compatible OSes!)
+ArchitecturesAllowed=x64compatible and not arm64
+
+; Never select 64-bit install mode but require a 64-bit OS anyway
+; (for example, because you're accessing HKLM64):
+ArchitecturesInstallIn64BitMode=
+ArchitecturesAllowed=win64
+</pre>
+</examples>
 <p><b>See also:</b><br/>
 <link topic="setup_architecturesinstallin64bitmode">ArchitecturesInstallIn64BitMode</link></p>
 </body>
@@ -5262,14 +5352,22 @@ DiskSliceSize=1457664
 <keyword value="x64" />
 <keyword value="IA-64" />
 <keyword value="Itanium" />
-<keyword value="ARM64" />
-<setupvalid>One or more of the following, separated by spaces: <br/><tt>x64</tt> <br/><tt>arm64</tt> <br/><tt>ia64</tt></setupvalid>
+<keyword value="Arm64" />
+<setupvalid>A space separated list of <link topic="archidentifiers">architecture identifiers</link>.<br />
+Or, a boolean expression containing <link topic="archidentifiers">architecture identifiers</link>. See <link topic="componentstasksparams">Components and Tasks parameters</link> for examples of boolean expressions.</setupvalid>
 <setupdefault><i>(blank)</i></setupdefault>
 <body>
 <p>Specifies the 64-bit processor architecture(s) on which Setup should install in <link topic="32vs64bitinstalls">64-bit install mode</link>. If this directive is not specified or is blank, Setup will always install in <link topic="32vs64bitinstalls">32-bit install mode</link>.</p>
 <p>Normally, you should not change this directive from its default value unless your application contains native 64-bit binaries.</p>
+<p>Should never match a 32-bit system otherwise Setup will show an internal error when started on such a system.</p>
 <p>Be sure you have read the <link topic="64bitlimitations">64-bit Installation Limitations</link> topic before setting this directive.</p>
 <p>If your application runs only on 64-bit processor architectures, you should set <link topic="setup_architecturesallowed">ArchitecturesAllowed</link> to the same value as this directive to prevent Setup from running on 32-bit Windows.</p>
+<example>
+<pre>
+; Select 64-bit install mode on any x64-compatible OS (x64 + Win11 Arm64):
+ArchitecturesInstallIn64BitMode=x64compatible
+</pre>
+</example>
 <p><b>See also:</b><br/>
 <link topic="setup_architecturesallowed">ArchitecturesAllowed</link></p>
 </body>

+ 22 - 1
ISHelp/isx.xml

@@ -772,11 +772,32 @@ external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath'; //A.dll
 </body>
 </topic>
 
-<topic name="scriptexpression" title="Pascal Scripting: Boolean Expressions">
+<topic name="scriptexpression" title="Pascal Scripting: Scripted Boolean Expressions">
+<keyword value="Pascal Scripting: Scripted Boolean Expressions" />
 <keyword value="Pascal Scripting: Boolean Expressions" />
 <body>
 <p>See <link topic="scriptcheck">Pascal Scripting: Check Parameters</link> for more information on boolean expressions and see <link topic="setup_uninstallable">Uninstallable</link> for an example.</p>
 </body>
 </topic>
 
+<topic name="isarchidentifier" title="Pascal Scripting: Architecture Identifier Matchers like IsX64Compatible">
+<keyword value="Pascal Scripting: Architecture Identifier Matchers like IsX64Compatible" />
+<keyword value="IsX64" />
+<keyword value="IsX86" />
+<body>
+<p>This is the list of support functions which test if the system matches an <link topic="archidentifiers">architecture identifier</link>:<br/><br/>
+<link topic="isxfunc_IsArm32Compatible">IsArm32Compatible</link><br/>
+<link topic="isxfunc_IsArm64">IsArm64</link><br/>
+<link topic="isxfunc_IsWin64">IsWin64</link><br/>
+<link topic="isxfunc_IsX64Compatible">IsX64Compatible</link><br/>
+<link topic="isxfunc_IsX64OS">IsX64OS</link><br/>
+<link topic="isxfunc_IsX86Compatible">IsX86Compatible</link><br/>
+<link topic="isxfunc_IsX86OS">IsX86OS</link><br/><br/>
+<link topic="isxfunc_IsX64OS">IsX64</link> (alias for IsX64OS; deprecated)<br/>
+<link topic="isxfunc_IsX86OS">IsX86</link> (alias for IsX86OS)<br/><br/></p>
+<p><b>See also:</b><br/>
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p>
+</body>
+</topic>
+
 </ishelp>

+ 47 - 45
ISHelp/isxfunc.xml

@@ -439,6 +439,7 @@ end;</pre></example>
         <name>IsWin64</name>
         <prototype>function IsWin64: Boolean;</prototype>
         <description><p>Returns True if the system is running a 64-bit version of Windows. If False is returned, you cannot utilize any of Inno Setup's 64-bit-only features.</p>
+<p>Another way to describe this function is: Returns True if the system matches architecture identifier<link topic="archidentifiers">win64</link>.</p>
 <p>Do not use this function to detect <link topic="32vs64bitinstalls">64-bit install mode</link>, use <link topic="isxfunc_Is64BitInstallMode">Is64BitInstallMode</link> instead.</p></description>
         <example><pre>begin
   // Check IsWin64 before using a 64-bit-only feature to
@@ -471,9 +472,10 @@ end;</pre></example>
         <prototype>function ProcessorArchitecture: TSetupProcessorArchitecture;</prototype>
         <description><p>Returns the native processor architecture of the current system.</p>
 <p>TSetupProcessorArchitecture is defined as:</p>
-<p><tt>TSetupProcessorArchitecture = (paUnknown, paX86, paX64, paIA64, paARM64);</tt></p></description>
+<p><tt>TSetupProcessorArchitecture = (paUnknown, paX86, paX64, paIA64, paArm64, paArm32);</tt></p></description>
         <remarks><p>A 64-bit processor architecture will never be returned on 32-bit versions of Windows. Hence, you cannot use this function to detect a 64-bit AMD CPU on a 32-bit version of Windows; you'll just get back <tt>paX86</tt> if you try.</p>
 <p><tt>paUnknown</tt> is returned if Setup/Uninstall does not recognize the processor architecture. It can be assumed that an "unknown" architecture is at least capable of executing 32-bit code, or Setup/Uninstall wouldn't be running at all.</p>
+<p><tt>paArm32</tt> is never returned because Setup/Uninstall does not run on 32-bit versions of Windows for Arm32.</p>
 <p>If <tt>paIA64</tt> is returned, and <tt>ia64</tt> is <i>not</i> included in the value of the <link topic="setup_architecturesinstallin64bitmode">ArchitecturesInstallIn64BitMode</link> [Setup] section directive, you should not assume that Inno Setup's 64-bit-only features are available -- for example, the <tt>{autopf64}</tt> constant. Those features only work when <link topic="isxfunc_IsWin64">IsWin64</link> returns True, and as documented, it may not return True on older Itanium versions of Windows that lack certain APIs Inno Setup requires.</p>
 <p>Therefore, instead of:</p>
 <pre>
@@ -501,58 +503,58 @@ begin
     paX86: S := 'x86';
     paX64: S := 'x64';
     paIA64: S := 'Itanium';
-    paARM64: S := 'ARM64';
+    paArm64: S := 'Arm64';
   else
     S := 'Unrecognized';
   end;
   MsgBox('Your processor architecture: ' + S, mbInformation, MB_OK);
 end;</pre></example>
-        <seealso><p><link topic="isxfunc_IsX86">IsX86</link><br />
-<link topic="isxfunc_IsX64">IsX64</link><br />
-<link topic="isxfunc_IsIA64">IsIA64</link><br />
-<link topic="isxfunc_IsARM64">IsARM64</link><br />
-<link topic="isxfunc_IsWin64">IsWin64</link><br />
+        <seealso><p><link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
 <link topic="isxfunc_Is64BitInstallMode">Is64BitInstallMode</link></p></seealso>
       </function>
       <function>
-        <name>IsX86</name>
-        <prototype>function IsX86: Boolean;</prototype>
-        <description><p>Returns True if the native processor architecture is x86.</p>
-<p>This function is a shorthand for <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link>. Be sure to read the <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link> topic before using this function.</p></description>
-        <seealso><p><link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link><br />
-<link topic="isxfunc_IsX64">IsX64</link><br />
-<link topic="isxfunc_IsIA64">IsIA64</link><br />
-<link topic="isxfunc_IsARM64">IsARM64</link></p></seealso>
-      </function>
-      <function>
-        <name>IsX64</name>
-        <prototype>function IsX64: Boolean;</prototype>
-        <description><p>Returns True if the native processor architecture is x64.</p>
-<p>This function is a shorthand for <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link>. Be sure to read the <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link> topic before using this function.</p></description>
-        <seealso><p><link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link><br />
-<link topic="isxfunc_IsX86">IsX86</link><br />
-<link topic="isxfunc_IsIA64">IsIA64</link><br />
-<link topic="isxfunc_IsARM64">IsARM64</link></p></seealso>
-      </function>
-      <function>
-        <name>IsIA64</name>
-        <prototype>function IsIA64: Boolean;</prototype>
-        <description><p>Returns True if the native processor architecture is ia64.</p>
-<p>This function is a shorthand for <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link>. Be sure to read the <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link> topic before using this function.</p></description>
-        <seealso><p><link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link><br />
-<link topic="isxfunc_IsX86">IsX86</link><br />
-<link topic="isxfunc_IsX64">IsX64</link><br />
-<link topic="isxfunc_IsARM64">IsARM64</link></p></seealso>
-      </function>
-      <function>
-        <name>IsARM64</name>
-        <prototype>function IsARM64: Boolean;</prototype>
-        <description><p>Returns True if the native processor architecture is arm64.</p>
-<p>This function is a shorthand for <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link>. Be sure to read the <link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link> topic before using this function.</p></description>
-        <seealso><p><link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link><br />
-<link topic="isxfunc_IsX86">IsX86</link><br />
-<link topic="isxfunc_IsX64">IsX64</link><br />
-<link topic="isxfunc_IsIA64">IsIA64</link></p></seealso>
+        <name>IsArm32Compatible</name>
+        <prototype>function IsArm32Compatible: Boolean;</prototype>
+        <description><p>Returns True if the system matches architecture identifier <link topic="archidentifiers">arm32compatible</link>.</p></description>
+        <seealso><p><link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p></seealso>
+      </function>
+      <function>
+        <name>IsArm64</name>
+        <prototype>function IsArm64: Boolean;</prototype>
+        <description><p>Returns True if the system matches architecture identifier <link topic="archidentifiers">arm64</link>.</p></description>
+        <seealso><p><link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p></seealso>
+      </function>
+      <function>
+        <name>IsX64Compatible</name>
+        <prototype>function IsX64Compatible: Boolean;</prototype>
+        <description><p>Returns True if the system matches architecture identifier <link topic="archidentifiers">x64compatible</link>.</p></description>
+        <seealso><p><link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p></seealso>
+      </function>
+      <function>
+        <name>IsX64OS</name>
+        <prototype>function IsX64OS: Boolean;</prototype>
+        <description><p>Returns True if the system matches architecture identifier <link topic="archidentifiers">x64os</link>.</p>
+<p>Before Inno Setup 6.3, <tt>IsX64OS</tt> was named <tt>IsX64</tt>. The compiler still accepts <tt>IsX64</tt> as an alias for <tt>IsX64OS</tt>, but will emit a deprecation warning when used.</p></description>
+        <seealso><p><link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p></seealso>
+      </function>
+      <function>
+        <name>IsX86Compatible</name>
+        <prototype>function IsX86Compatible: Boolean;</prototype>
+        <description><p>Returns True if the system matches architecture identifier <link topic="archidentifiers">x86compatible</link>.</p></description>
+        <seealso><p><link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p></seealso>
+      </function>
+      <function>
+        <name>IsX86OS</name>
+        <prototype>function IsX86OS: Boolean;</prototype>
+        <description><p>Returns True if the system matches architecture identifier <link topic="archidentifiers">x86os</link>.</p>
+<p>Before Inno Setup 6.3, <tt>IsX86OS</tt> was named <tt>IsX86</tt>. The compiler still accepts <tt>IsX86</tt> as an alias for <tt>IsX86OS</tt>.</p></description>
+        <seealso><p><link topic="isarchidentifier">Architecture Identifier Matchers like IsX64Compatible</link><br />
+<link topic="isxfunc_ProcessorArchitecture">ProcessorArchitecture</link></p></seealso>
       </function>
     </subcategory>
     <subcategory>

+ 4 - 0
Projects/Src/CompMsgs.pas

@@ -203,6 +203,9 @@ const
   SCompilerDirectivePatternTooLong = 'The [Setup] section directive "%s" contains a pattern that is too long';
   SCompilerOutputBaseFileNameSetup = 'Setting the [Setup] section directive "OutputBaseFileName" to "setup" is not recommended: all executables named "setup.exe" are shimmed by Windows application compatibility to load additional DLLs, such as version.dll.' + ' These DLLs are loaded unsafely by Windows and can be hijacked. Use a different name, for example "mysetup".';
   SCompilerWizImageRenamed = 'Wizard image "%s" has been renamed. Use "%s" instead or consider removing the directive to use modern built-in wizard images.';
+  SCompilerArchitectureIdentifierInvalid = 'Architecture identifier "%s" is invalid';
+  SCompilerArchitectureIdentifierDeprecatedWarning = 'Architecture identifier "%s" is deprecated. ' +
+    'Substituting "%s", but note that "%s" is preferred in most cases. See the "Architecture Identifiers" topic in help file for more information.';
 
   { Signing }
   SCompilerSignatureNeeded = 'Signed uninstaller mode is enabled. Using ' +
@@ -309,6 +312,7 @@ const
   SCompilerCodeUnsupportedEventFunction = 'Event function named "%s" is no longer supported. Create a "%s" function instead';
   SCompilerCodeFunctionRenamed = 'Support function "%s" has been renamed. Use "%s" instead.';
   SCompilerCodeFunctionRenamedWithAlternative = 'Support function "%s" has been renamed. Use "%s" instead or consider using "%s".';
+  SCompilerCodeFunctionDeprecatedWithAlternativeAndDocs = 'Support function "%s" is deprecated. Use "%s" instead, but note that "%s" is preferred in most cases. See the "%s" topic in help file for more information.';
 
   { [Types] }
   SCompilerTypesCustomTypeAlreadyDefined = 'A custom type has already been defined';

+ 31 - 26
Projects/Src/Compile.pas

@@ -30,7 +30,7 @@ implementation
 
 uses
   CompPreprocInt, Commctrl, Consts, Classes, IniFiles, TypInfo, AnsiStrings, Math,
-  Generics.Collections, WideStrUtils,
+  Generics.Collections, StrUtils, WideStrUtils,
   PathFunc, CmnFunc2, Struct, Int64Em, CompMsgs, SetupEnt,
   FileClass, Compress, CompressZlib, bzlib, LZMA, ArcFour, SHA1,
   MsgIDs, SetupSectionDirectives, LangOptionsSectionDirectives, DebugStruct, VerInfo, ResUpdate, CompExeUpdate,
@@ -309,6 +309,8 @@ type
       var AOnlyBelowVersion: TSetupVersionData);
     procedure ProcessPermissionsParameter(ParamData: String;
       const AccessMasks: array of TNameAndAccessMask; var PermissionsEntry: Smallint);
+    function EvalArchitectureIdentifier(Sender: TSimpleExpression; const Name: String;
+      const Parameters: array of const): Boolean;
     function EvalComponentIdentifier(Sender: TSimpleExpression; const Name: String;
       const Parameters: array of const): Boolean;
     function EvalTaskIdentifier(Sender: TSimpleExpression; const Name: String;
@@ -2907,6 +2909,26 @@ begin
   CommaText := CommaText + S;
 end;
 
+function TSetupCompiler.EvalArchitectureIdentifier(Sender: TSimpleExpression;
+  const Name: String; const Parameters: array of const): Boolean;
+const
+  ArchIdentifiers: array[0..9] of String = (
+    'arm32compatible', 'arm64', 'ia64', 'win64',
+    'x64', 'x64os', 'x64compatible',
+    'x86', 'x86os', 'x86compatible');
+begin
+  for var ArchIdentifier in ArchIdentifiers do begin
+    if Name = ArchIdentifier then begin
+      if ArchIdentifier = 'x64' then
+        WarningsList.Add(Format(SCompilerArchitectureIdentifierDeprecatedWarning, ['x64', 'x64os', 'x64compatible']));
+      Exit(True); { Result doesn't matter }
+    end;
+  end;
+
+  raise Exception.CreateFmt(SCompilerArchitectureIdentifierInvalid, [Name]);
+end;
+
+{ Sets the Used properties while evaluating }
 function TSetupCompiler.EvalComponentIdentifier(Sender: TSimpleExpression; const Name: String;
   const Parameters: array of const): Boolean;
 var
@@ -2928,6 +2950,7 @@ begin
   Result := True;  { Result doesn't matter }
 end;
 
+{ Sets the Used properties while evaluating }
 function TSetupCompiler.EvalTaskIdentifier(Sender: TSimpleExpression; const Name: String;
   const Parameters: array of const): Boolean;
 var
@@ -2971,13 +2994,13 @@ procedure TSetupCompiler.ProcessExpressionParameter(const ParamName,
 var
   SimpleExpression: TSimpleExpression;
 begin
-  ProcessedParamData := ParamData;
+  ProcessedParamData := Trim(ParamData);
 
   if ProcessedParamData <> '' then begin
     if SlashConvert then
       StringChange(ProcessedParamData, '/', '\');
-    { Check the expression in ParamData and set the Used properties while
-      evaluating. Use non-Lazy checking to make sure everything is evaluated. }
+    { Check the expression in ParamData. Use non-Lazy checking to make sure
+      everything is evaluated. }
     try
       SimpleExpression := TSimpleExpression.Create;
       try
@@ -3404,26 +3427,6 @@ var
     TouchTimeSecond := Second;
   end;
 
-  function StrToArchitectures(S: String; const Only64Bit: Boolean): TSetupProcessorArchitectures;
-  const
-    ProcessorFlags: array[0..3] of PChar = ('x86', 'x64', 'ia64', 'arm64');
-  begin
-    Result := [];
-    while True do
-      case ExtractFlag(S, ProcessorFlags) of
-        -2: Break;
-        -1: Invalid;
-        0: if Only64Bit then
-             Invalid
-           else
-             Include(Result, paX86);
-        1: Include(Result, paX64);
-        2: Include(Result, paIA64);
-        3: Include(Result, paARM64);
-      end;
-  end;
-
-
   function StrToPrivilegesRequiredOverrides(S: String): TSetupPrivilegesRequiredOverrides;
   const
     Overrides: array[0..1] of PChar = ('commandline', 'dialog');
@@ -3560,10 +3563,12 @@ begin
         SetupHeader.AppVersion := Value;
       end;
     ssArchitecturesAllowed: begin
-        SetupHeader.ArchitecturesAllowed := StrToArchitectures(Value, False);
+        ProcessExpressionParameter(KeyName, LowerCase(Value),
+          EvalArchitectureIdentifier, False, SetupHeader.ArchitecturesAllowed);
       end;
     ssArchitecturesInstallIn64BitMode: begin
-        SetupHeader.ArchitecturesInstallIn64BitMode := StrToArchitectures(Value, True);
+        ProcessExpressionParameter(KeyName, LowerCase(Value),
+          EvalArchitectureIdentifier, False, SetupHeader.ArchitecturesInstallIn64BitMode);
       end;
     ssASLRCompatible: begin
         ASLRCompatible := StrToBool(Value);

+ 2 - 3
Projects/Src/Helper.pas

@@ -112,11 +112,10 @@ var
 function GetHelperResourceName: String;
 begin
   {$R HelperEXEs.res}
-  case ProcessorArchitecture of
-    paX64: Result := 'HELPER_EXE_AMD64';
+  if paX64 in MachineTypesSupportedBySystem then
+    Result := 'HELPER_EXE_AMD64'
   else
     Result := '';
-  end;
 end;
 
 procedure SetHelperExeFilename(const Filename: String);

+ 156 - 63
Projects/Src/Main.pas

@@ -172,6 +172,7 @@ var
   InstallDefaultRegView: TRegView = rvDefault;
   HasCustomType, HasComponents, HasTasks: Boolean;
   ProcessorArchitecture: TSetupProcessorArchitecture = paUnknown;
+  MachineTypesSupportedBySystem: TSetupProcessorArchitectures;
   WindowsVersion: Cardinal;
   NTServicePackLevel: Word;
   WindowsProductType: Byte;
@@ -245,6 +246,7 @@ procedure SetTaskbarButtonVisibility(const AVisible: Boolean);
 procedure ShellExecuteAsOriginalUser(hWnd: HWND; Operation, FileName, Parameters, Directory: LPWSTR; ShowCmd: Integer); stdcall;
 function ShouldDisableFsRedirForFileEntry(const FileEntry: PSetupFileEntry): Boolean;
 function ShouldDisableFsRedirForRunEntry(const RunEntry: PSetupRunEntry): Boolean;
+function EvalArchitectureIdentifier(const Name: String): Boolean;
 function EvalDirectiveCheck(const Expression: String): Boolean;
 function ShouldProcessEntry(const WizardComponents, WizardTasks: TStringList;
   const Components, Tasks, Languages, Check: String): Boolean;
@@ -292,6 +294,8 @@ type
         const Constant: String): String;
       class function EvalInstallIdentifier(Sender: TSimpleExpression;
         const Name: String; const Parameters: array of const): Boolean;
+      class function EvalArchitectureIdentifier(Sender: TSimpleExpression;
+        const Name: String; const Parameters: array of const): Boolean;
       class function EvalComponentOrTaskIdentifier(Sender: TSimpleExpression;
         const Name: String; const Parameters: array of const): Boolean;
       class function EvalLanguageIdentifier(Sender: TSimpleExpression;
@@ -486,6 +490,47 @@ begin
   CheckOrInstallCurrentSourceFilename := '';
 end;
 
+function EvalArchitectureIdentifier(const Name: String): Boolean;
+type
+  TArchIdentifierRec = record
+    Name: String;
+    Arch: TSetupProcessorArchitecture;
+    Compatible: Boolean;
+  end;
+const
+  { Valid identifier 'win64' is not in this list but treated specially below }
+  ArchIdentifiers: array[0..8] of TArchIdentifierRec = (
+    (Name: 'arm32compatible'; Arch: paArm32; Compatible: True),
+    (Name: 'arm64'; Arch: paArm64; Compatible: False),
+    (Name: 'ia64'; Arch: paIA64; Compatible: False),
+    (Name: 'x64'; Arch: paX64; Compatible: False),
+    (Name: 'x64os'; Arch: paX64; Compatible: False),
+    (Name: 'x64compatible'; Arch: paX64; Compatible: True),
+    (Name: 'x86'; Arch: paX86; Compatible: False),
+    (Name: 'x86os'; Arch: paX86; Compatible: False),
+    (Name: 'x86compatible'; Arch: paX86; Compatible: True));
+begin
+  if Name = 'win64' then
+    Exit(IsWin64);
+
+  for var ArchIdentifier in ArchIdentifiers do
+    if ArchIdentifier.Name = Name then begin
+      if ArchIdentifier.Compatible then
+        Exit(ArchIdentifier.Arch in MachineTypesSupportedBySystem)
+      else { An exact match is requested instead of anything compatible, perhaps
+             for a driver install or something similar }
+        Exit(ProcessorArchitecture = ArchIdentifier.Arch);
+    end;
+
+  raise Exception.CreateFmt('Unknown architecture ''%s''', [Name]);
+end;
+
+class function TDummyClass.EvalArchitectureIdentifier(Sender: TSimpleExpression;
+  const Name: String; const Parameters: array of const): Boolean;
+begin
+  Result := Main.EvalArchitectureIdentifier(Name);
+end;
+
 class function TDummyClass.EvalComponentOrTaskIdentifier(Sender: TSimpleExpression;
   const Name: String; const Parameters: array of const): Boolean;
 var
@@ -537,34 +582,33 @@ begin
     Result := EvalCheck(Expression);
 end;
 
-function ShouldProcessEntry(const WizardComponents, WizardTasks: TStringList;
-  const Components, Tasks, Languages, Check: String): Boolean;
-
-  function EvalExpression(const Expression: String;
-    OnEvalIdentifier: TSimpleExpressionOnEvalIdentifier; Tag: LongInt): Boolean;
-  var
-    SimpleExpression: TSimpleExpression;
-  begin
+function EvalExpression(const Expression: String;
+  OnEvalIdentifier: TSimpleExpressionOnEvalIdentifier; Tag: LongInt = 0): Boolean;
+var
+  SimpleExpression: TSimpleExpression;
+begin
+  try
+    SimpleExpression := TSimpleExpression.Create;
     try
-      SimpleExpression := TSimpleExpression.Create;
-      try
-        SimpleExpression.Lazy := True;
-        SimpleExpression.Expression := Expression;
-        SimpleExpression.OnEvalIdentifier := OnEvalIdentifier;
-        SimpleExpression.ParametersAllowed := False;
-        SimpleExpression.SilentOrAllowed := True;
-        SimpleExpression.SingleIdentifierMode := False;
-        SimpleExpression.Tag := Tag;
-        Result := SimpleExpression.Eval;
-      finally
-        SimpleExpression.Free;
-      end;
-    except
-      InternalError(Format('Expression error ''%s''', [GetExceptMessage]));
-      Result := False;
+      SimpleExpression.Lazy := True;
+      SimpleExpression.Expression := Expression;
+      SimpleExpression.OnEvalIdentifier := OnEvalIdentifier;
+      SimpleExpression.ParametersAllowed := False;
+      SimpleExpression.SilentOrAllowed := True;
+      SimpleExpression.SingleIdentifierMode := False;
+      SimpleExpression.Tag := Tag;
+      Result := SimpleExpression.Eval;
+    finally
+      SimpleExpression.Free;
     end;
+  except
+    InternalError(Format('Expression error ''%s''', [GetExceptMessage]));
+    Result := False;
   end;
+end;
 
+function ShouldProcessEntry(const WizardComponents, WizardTasks: TStringList;
+  const Components, Tasks, Languages, Check: String): Boolean;
 var
   ProcessComponent, ProcessTask, ProcessLanguage: Boolean;
 begin
@@ -580,7 +624,7 @@ begin
       ProcessTask := True;
 
     if Languages <> '' then
-      ProcessLanguage := EvalExpression(Languages, TDummyClass.EvalLanguageIdentifier, 0)
+      ProcessLanguage := EvalExpression(Languages, TDummyClass.EvalLanguageIdentifier)
     else
       ProcessLanguage := True;
 
@@ -2257,6 +2301,27 @@ begin
 end;
 
 procedure LogWindowsVersion;
+
+  function ArchitecturesToStr(const Architectures: TSetupProcessorArchitectures;
+    const Separator: String): String;
+
+    procedure AppendArchitecture(var S: String; const Separator, L: String);
+    begin
+      if S <> '' then
+        S := S + Separator + L
+      else
+        S := L;
+    end;
+
+  var
+    I: TSetupProcessorArchitecture;
+  begin
+    Result := '';
+    for I := Low(I) to High(I) do
+      if I in Architectures then
+        AppendArchitecture(Result, Separator, SetupProcessorArchitectureNames[I]);
+  end;
+
 var
   SP: String;
 begin
@@ -2269,6 +2334,7 @@ begin
     (WindowsVersion shr 16) and $FF, WindowsVersion and $FFFF, SP, SYesNo[True]]);
   LogFmt('64-bit Windows: %s', [SYesNo[IsWin64]]);
   LogFmt('Processor architecture: %s', [SetupProcessorArchitectureNames[ProcessorArchitecture]]);
+  LogFmt('Machine types supported by system: %s', [ArchitecturesToStr(MachineTypesSupportedBySystem, ' ')]);
 
   if IsAdmin then
     Log('User privileges: Administrative')
@@ -2520,25 +2586,6 @@ var
     Delete(S, 1, P);
   end;
 
-  function ArchitecturesToStr(const Architectures: TSetupProcessorArchitectures): String;
-
-    procedure AppendLine(var S: String; const L: String);
-    begin
-      if S <> '' then
-        S := S + #13#10 + L
-      else
-        S := L;
-    end;
-
-  var
-    I: TSetupProcessorArchitecture;
-  begin
-    Result := '';
-    for I := Low(I) to High(I) do
-      if I in Architectures then
-        AppendLine(Result, SetupProcessorArchitectureNames[I]);
-  end;
-
   procedure AbortInit(const Msg: TSetupMessageID);
   begin
     LoggedMsgBox(SetupMessages[Msg], '', mbCriticalError, MB_OK, True, IDOK);
@@ -3040,11 +3087,15 @@ begin
         { Set Is64BitInstallMode if we're on Win64 and the processor architecture is
           one on which a "64-bit mode" install should be performed. Doing this early
           so that UsePreviousPrivileges knows where to look. Will log later. }
-        if ProcessorArchitecture in SetupHeader.ArchitecturesInstallIn64BitMode then begin
+        if (SetupHeader.ArchitecturesInstallIn64BitMode <> '') and
+           EvalExpression(SetupHeader.ArchitecturesInstallIn64BitMode, TDummyClass.EvalArchitectureIdentifier) then begin
           if not IsWin64 then begin
-            { A 64-bit processor was detected and 64-bit install mode was requested,
-              but IsWin64 is False, indicating required WOW64 APIs are not present }
-            AbortInit(msgWindowsVersionNotSupported);
+            { The script writer made a mistake: their expression matched a
+              32-bit system. Obviously that can't be allowed.
+              With "not" there are lots of ways that could happen without
+              explicitly specifying a 32-bit architecture in the expression.
+              One example: "not win64" }
+            InternalError('ArchitecturesInstallIn64BitMode expression matched 32-bit system');
           end;
           Initialize64BitInstallMode(True);
         end
@@ -3203,9 +3254,9 @@ begin
   end;
   
   { Check processor architecture }
-  if (SetupHeader.ArchitecturesAllowed <> []) and
-     not(ProcessorArchitecture in SetupHeader.ArchitecturesAllowed) then
-    AbortInitFmt1(msgOnlyOnTheseArchitectures, ArchitecturesToStr(SetupHeader.ArchitecturesAllowed));
+  if (SetupHeader.ArchitecturesAllowed <> '') and
+     not EvalExpression(SetupHeader.ArchitecturesAllowed, TDummyClass.EvalArchitectureIdentifier) then
+    AbortInit(msgWindowsVersionNotSupported);
 
   { Check Windows version }
   case InstallOnThisVersion(SetupHeader.MinVersion, SetupHeader.OnlyBelowVersion) of
@@ -4328,25 +4379,25 @@ begin
 end;
 
 
-procedure InitIsWin64AndProcessorArchitecture;
+procedure InitIsWin64AndProcessorArchitectureAndMachineTypesSupportedBySystem;
 const
-  PROCESSOR_ARCHITECTURE_INTEL = 0;
-  PROCESSOR_ARCHITECTURE_IA64 = 6;
-  PROCESSOR_ARCHITECTURE_AMD64 = 9;
   PROCESSOR_ARCHITECTURE_ARM64 = 12;
-  IMAGE_FILE_MACHINE_I386 = $014c;
-  IMAGE_FILE_MACHINE_IA64 = $0200;
-  IMAGE_FILE_MACHINE_AMD64 = $8664;
   IMAGE_FILE_MACHINE_ARM64 = $AA64;
+  IMAGE_FILE_MACHINE_ARMNT = $01C4;
+  UserEnabled = $1;
 var
   KernelModule: HMODULE;
   GetNativeSystemInfoFunc: procedure(var lpSystemInfo: TSystemInfo); stdcall;
   IsWow64ProcessFunc: function(hProcess: THandle; var Wow64Process: BOOL): BOOL; stdcall;
   IsWow64Process2Func: function(hProcess: THandle; var pProcessMachine, pNativeMachine: USHORT): BOOL; stdcall;
+  GetMachineTypeAttributesFunc: function(Machine: USHORT; var MachineTypeAttributes: Integer): HRESULT; stdcall;
+  IsWow64GuestMachineSupportedFunc: function(WowGuestMachine: USHORT; var MachineIsSupported: BOOL): HRESULT; stdcall;
   ProcessMachine, NativeMachine: USHORT;
   Wow64Process: BOOL;
   SysInfo: TSystemInfo;
 begin
+  KernelModule := GetModuleHandle(kernel32);
+
   { The system is considered a "Win64" system if all of the following
     conditions are true:
     1. One of the following two is true:
@@ -4358,10 +4409,9 @@ begin
     4. GetSystemWow64DirectoryA is available.
     5. RegDeleteKeyExA is available.
     The system does not have to be one of the known 64-bit architectures
-    (AMD64, IA64, ARM64) to be considered a "Win64" system. }
+    (AMD64, IA64, Arm64) to be considered a "Win64" system. }
 
   IsWin64 := False;
-  KernelModule := GetModuleHandle(kernel32);
 
   IsWow64Process2Func := GetProcAddress(KernelModule, 'IsWow64Process2');
   if Assigned(IsWow64Process2Func) and
@@ -4372,7 +4422,7 @@ begin
       IMAGE_FILE_MACHINE_I386: ProcessorArchitecture := paX86;
       IMAGE_FILE_MACHINE_IA64: ProcessorArchitecture := paIA64;
       IMAGE_FILE_MACHINE_AMD64: ProcessorArchitecture := paX64;
-      IMAGE_FILE_MACHINE_ARM64: ProcessorArchitecture := paARM64;
+      IMAGE_FILE_MACHINE_ARM64: ProcessorArchitecture := paArm64;
     else
       ProcessorArchitecture := paUnknown;
     end;
@@ -4392,7 +4442,7 @@ begin
       PROCESSOR_ARCHITECTURE_INTEL: ProcessorArchitecture := paX86;
       PROCESSOR_ARCHITECTURE_IA64: ProcessorArchitecture := paIA64;
       PROCESSOR_ARCHITECTURE_AMD64: ProcessorArchitecture := paX64;
-      PROCESSOR_ARCHITECTURE_ARM64: ProcessorArchitecture := paARM64;
+      PROCESSOR_ARCHITECTURE_ARM64: ProcessorArchitecture := paArm64;
     else
       ProcessorArchitecture := paUnknown;
     end;
@@ -4403,6 +4453,49 @@ begin
           (GetProcAddress(KernelModule, 'GetSystemWow64DirectoryA') <> nil) and
           (GetProcAddress(GetModuleHandle(advapi32), 'RegDeleteKeyExA') <> nil)) then
     IsWin64 := False;
+
+  { Setup MachineTypesSupportedBySystem. The result should end up being:
+    - 32-bit x86: [paX86]
+    - x64: [paX86, paX64]
+      (but not paX86 in a future x64 build of Inno Setup if Windows was installed
+       without support for x86 binaries (which is possible with Windows Server))
+    - Itanium: [paX86, paIA64]
+    - Arm64 Windows 10: [paX86, paArm64, paArm32]
+      (Arm32 support detected, not just assumed)
+    - Arm64 Windows 11: [paX86, paX64, paArm64, paArm32]
+      (X64 and Arm32 support detected, not just assumed) }
+
+  {$IFDEF CPUX86}
+  MachineTypesSupportedBySystem := [paX86];
+  {$ELSE}
+  {$MESSAGE ERROR 'This needs updating for non-x86 builds'}
+  {$ENDIF}
+
+  if ProcessorArchitecture <> paUnknown then
+    Include(MachineTypesSupportedBySystem, ProcessorArchitecture);
+
+  { On Windows 11 we can use GetMachineTypeAttributes to check what is supported extra }
+  GetMachineTypeAttributesFunc := GetProcAddress(KernelModule, 'GetMachineTypeAttributes');
+  if Assigned(GetMachineTypeAttributesFunc) then begin
+    var MachineTypeAttributes: Integer;
+    if (GetMachineTypeAttributesFunc(IMAGE_FILE_MACHINE_ARMNT, MachineTypeAttributes) = S_OK) and
+       ((MachineTypeAttributes and UserEnabled) <> 0) then
+      Include(MachineTypesSupportedBySystem, paArm32);
+    if not (paX64 in MachineTypesSupportedBySystem) and
+       (GetMachineTypeAttributesFunc(IMAGE_FILE_MACHINE_AMD64, MachineTypeAttributes) = S_OK) and
+       ((MachineTypeAttributes and UserEnabled) <> 0) then
+      Include(MachineTypesSupportedBySystem, paX64);
+  end else begin
+    { Without GetMachineTypeAttributes we can only check if Arm32 is supported extra
+      using IsWow64GuestMachineSupported }
+    IsWow64GuestMachineSupportedFunc := GetProcAddress(KernelModule, 'IsWow64GuestMachineSupported');
+    if Assigned(IsWow64GuestMachineSupportedFunc) then begin
+      var MachineIsSupported: BOOL;
+      if (IsWow64GuestMachineSupportedFunc(IMAGE_FILE_MACHINE_ARMNT, MachineIsSupported) = S_OK) and
+          MachineIsSupported then
+        Include(MachineTypesSupportedBySystem, paArm32);
+    end;
+  end;
 end;
 
 procedure InitWindowsVersion;
@@ -4486,7 +4579,7 @@ begin
 end;
 
 initialization
-  InitIsWin64AndProcessorArchitecture;
+  InitIsWin64AndProcessorArchitectureAndMachineTypesSupportedBySystem;
   InitWindowsVersion;
   InitComponents := TStringList.Create();
   InitTasks := TStringList.Create();

+ 10 - 5
Projects/Src/ScriptFunc.pas

@@ -201,7 +201,7 @@ const
   );
 
   { Main }
-  MainTable: array [0..28] of AnsiString =
+  MainTable: array [0..33] of AnsiString =
   (
     'function GetWizardForm: TWizardForm;',
     'function GetMainForm: TMainForm;',
@@ -225,10 +225,15 @@ const
     'function IsWin64: Boolean;',
     'function Is64BitInstallMode: Boolean;',
     'function ProcessorArchitecture: TSetupProcessorArchitecture;',
-    'function IsX86: Boolean;',
-    'function IsX64: Boolean;',
-    'function IsIA64: Boolean;',
-    'function IsARM64: Boolean;',
+    'function IsArm32Compatible: Boolean',
+    'function IsArm64: Boolean',
+    'function IsIA64: Boolean',
+    'function IsX64: Boolean',
+    'function IsX64OS: Boolean',
+    'function IsX64Compatible: Boolean',
+    'function IsX86: Boolean',
+    'function IsX86OS: Boolean',
+    'function IsX86Compatible: Boolean',
     'function CustomMessage(const MsgName: String): String;',
     'function RmSessionStarted: Boolean;',
     'function RegisterExtraCloseApplicationsResource(const DisableFsRedir: Boolean; const AFilename: String): Boolean;'

+ 1 - 0
Projects/Src/ScriptFunc_C.pas

@@ -157,6 +157,7 @@ begin
   RegisterFunctionTable(MainTable);
   ObsoleteFunctionWarnings.Add('IsComponentSelected', Format(SCompilerCodeFunctionRenamed, ['IsComponentSelected', 'WizardIsComponentSelected']));
   ObsoleteFunctionWarnings.Add('IsTaskSelected', Format(SCompilerCodeFunctionRenamed, ['IsTaskSelected', 'WizardIsTaskSelected']));
+  ObsoleteFunctionWarnings.Add('IsX64', Format(SCompilerCodeFunctionDeprecatedWithAlternativeAndDocs, ['IsX64', 'IsX64OS', 'IsX64Compatible', 'Architecture Identifiers']));
   RegisterFunctionTable(MsgsTable);
   RegisterDelphiFunctionTable(MsgsDelphiTable);
   RegisterFunctionTable(SystemTable);

+ 5 - 8
Projects/Src/ScriptFunc_R.pas

@@ -1094,14 +1094,11 @@ begin
     Stack.SetBool(PStart, Is64BitInstallMode);
   end else if Proc.Name = 'PROCESSORARCHITECTURE' then begin
     Stack.SetInt(PStart, Integer(ProcessorArchitecture));
-  end else if Proc.Name = 'ISX86' then begin
-    Stack.SetBool(PStart, ProcessorArchitecture = paX86);
-  end else if Proc.Name = 'ISX64' then begin
-    Stack.SetBool(PStart, ProcessorArchitecture = paX64);
-  end else if Proc.Name = 'ISIA64' then begin
-    Stack.SetBool(PStart, ProcessorArchitecture = paIA64);
-  end else if Proc.Name = 'ISARM64' then begin
-    Stack.SetBool(PStart, ProcessorArchitecture = paARM64);
+  end else if (Proc.Name = 'ISARM32COMPATIBLE') or (Proc.Name = 'ISARM64') or (Proc.Name = 'ISIA64') or
+              (Proc.Name = 'ISX64') or (Proc.Name = 'ISX64OS') or (Proc.Name = 'ISX64COMPATIBLE') or
+              (Proc.Name = 'ISX86') or (Proc.Name = 'ISX86OS') or (Proc.Name = 'ISX86COMPATIBLE') then begin
+    var ArchitectureIdentifier := LowerCase(Copy(String(Proc.Name), 3, MaxInt));
+    Stack.SetBool(PStart, EvalArchitectureIdentifier(ArchitectureIdentifier));
   end else if Proc.Name = 'CUSTOMMESSAGE' then begin
     Stack.SetString(PStart, CustomMessage(Stack.GetString(PStart-1)));
   end else if Proc.Name = 'RMSESSIONSTARTED' then begin

+ 5 - 5
Projects/Src/Struct.pas

@@ -69,7 +69,7 @@ type
   TSetupLanguageDetectionMethod = (ldUILanguage, ldLocale, ldNone);
   TSetupCompressMethod = (cmStored, cmZip, cmBzip, cmLZMA, cmLZMA2);
   TSetupSalt = array[0..7] of Byte;
-  TSetupProcessorArchitecture = (paUnknown, paX86, paX64, paIA64, paARM64);
+  TSetupProcessorArchitecture = (paUnknown, paX86, paX64, paIA64, paArm32, paArm64);
   TSetupProcessorArchitectures = set of TSetupProcessorArchitecture;
   TSetupDisablePage = (dpAuto, dpNo, dpYes);
   TSetupPrivilegesRequired = (prNone, prPowerUser, prAdmin, prLowest);
@@ -78,10 +78,10 @@ type
   TSetupWizardStyle = (wsClassic, wsModern);
 const
   SetupProcessorArchitectureNames: array[TSetupProcessorArchitecture] of String =
-    ('Unknown', 'x86', 'x64', 'Itanium', 'ARM64');
+    ('Unknown', 'x86', 'x64', 'Itanium', 'Arm32', 'Arm64');
 
 const
-  SetupHeaderStrings = 30;
+  SetupHeaderStrings = 32;
   SetupHeaderAnsiStrings = 4;
 type
   TSetupHeader = packed record
@@ -91,7 +91,8 @@ type
       UninstallDisplayIcon, AppMutex, DefaultUserInfoName, DefaultUserInfoOrg,
       DefaultUserInfoSerial, AppReadmeFile, AppContact, AppComments,
       AppModifyPath, CreateUninstallRegKey, Uninstallable, CloseApplicationsFilter,
-      SetupMutex, ChangesEnvironment, ChangesAssociations: String;
+      SetupMutex, ChangesEnvironment, ChangesAssociations,
+      ArchitecturesAllowed, ArchitecturesInstallIn64BitMode: String;
     LicenseText, InfoBeforeText, InfoAfterText, CompiledCodeText: AnsiString;
     NumLanguageEntries, NumCustomMessageEntries, NumPermissionEntries,
       NumTypeEntries, NumComponentEntries, NumTaskEntries, NumDirEntries,
@@ -114,7 +115,6 @@ type
     ShowLanguageDialog: (slYes, slNo, slAuto);
     LanguageDetectionMethod: TSetupLanguageDetectionMethod;
     CompressMethod: TSetupCompressMethod;
-    ArchitecturesAllowed, ArchitecturesInstallIn64BitMode: TSetupProcessorArchitectures;
     DisableDirPage, DisableProgramGroupPage: TSetupDisablePage;
     UninstallDisplaySize: Integer64;
     Options: set of TSetupHeaderOption;

+ 1 - 1
setup.iss

@@ -170,7 +170,7 @@ Source: "Examples\Languages.iss"; DestDir: "{app}\Examples"; Flags: ignoreversio
 Source: "Examples\MyDll.dll"; DestDir: "{app}\Examples"; Flags: ignoreversion signonce touch
 Source: "Examples\MyProg.chm"; DestDir: "{app}\Examples"; Flags: ignoreversion touch
 Source: "Examples\MyProg.exe"; DestDir: "{app}\Examples"; Flags: ignoreversion signonce touch
-Source: "Examples\MyProg-ARM64.exe"; DestDir: "{app}\Examples"; Flags: ignoreversion signonce touch
+Source: "Examples\MyProg-Arm64.exe"; DestDir: "{app}\Examples"; Flags: ignoreversion signonce touch
 Source: "Examples\MyProg-x64.exe"; DestDir: "{app}\Examples"; Flags: ignoreversion signonce touch
 Source: "Examples\Readme.txt"; DestDir: "{app}\Examples"; Flags: ignoreversion touch
 Source: "Examples\Readme-Dutch.txt"; DestDir: "{app}\Examples"; Flags: ignoreversion touch

+ 60 - 0
whatsnew.htm

@@ -45,6 +45,66 @@ For conditions of distribution and use, see <a href="https://jrsoftware.org/file
   </ul>
   </li>
 </ul>
+<p><span class="head2">Support for processor architectures improved</span></p>
+<ul>
+  <li>Setup can now detect support for x64 emulation when running on Windows 11 for Arm, and can be instructed to select 64-bit install mode in that case which was not possible before. See the first example below.<br/><br/></li>
+  <li>[Setup] section directives <tt>ArchitecturesInstallIn64BitMode</tt> and <tt>ArchitecturesAllowed</tt> now both support boolean expressions. Additionally, extra platform identifiers were added. This enables for example:
+      <pre>; Select 64-bit install mode on any x64-compatible OS (x64 + Win11 Arm64):
+ArchitecturesInstallIn64BitMode=x64compatible
+
+; Only allow installation on systems that aren't x64-compatible.
+; Useful in a situation where you have separate x86 & x64 installers,
+; and don't want users of x64-compatible OSes (x64 + Win11 Arm64)
+; erroneously running the x86 installer which would say:
+ArchitecturesAllowed=not x64compatible
+
+; Require two arch matches at the same time:
+; If an Arm installer installs both Arm64 and Arm32 binaries,
+; you technically should ensure that the OS actually supports both:
+ArchitecturesAllowed=arm64 and arm32compatible
+
+; Same goes for an x64-compatible installer shipping some 32-bit
+; binaries:
+ArchitecturesAllowed=x64compatible and x86compatible
+
+; Installing a component that cannot operate in an emulated
+; environment, such as an x64 device driver:
+ArchitecturesAllowed=x64os
+
+; Allow installation on x64-compatible systems, but deny one of them:
+; (Imagine if in the future there were 3 x64-compatible OSes!)
+ArchitecturesAllowed=x64compatible and not arm64
+
+; Never select 64-bit install mode but require a 64-bit OS anyway
+; (for example, because you're accessing HKLM64):
+ArchitecturesInstallIn64BitMode=
+ArchitecturesAllowed=win64</pre>
+      The full list of new platform identifiers is: <tt>arm32compatible</tt>, <tt>x64compatible</tt>, <tt>x64os</tt>, <tt>x86compatible</tt>, <tt>x86os</tt>, and <tt>win64</tt>. See the new "Architecture Identifiers" help topic for more details.<br/><br/>
+      All of the above is backward compatible so no changes are needed for your existing scripts. For example, this works unchanged (but see the updated <i>64BitThreeArch.iss</i> example script for the preferred setting):
+      <pre>ArchitecturesInstallIn64BitMode=x64 arm64</pre>
+      Do note that the <tt>x64</tt> indentifier is now deprecated and the compiler will issue a warning if you use it anyway. It will substitute <tt>x64os</tt>, but <tt>x64compatible</tt> is preferred in most cases and it's simple to adopt it: just replace <tt>x64</tt> with <tt>x64compatible</tt>, and any <tt>IsX64</tt> with <tt>IsX64Compatible</tt>.<br/><br/>
+      The 64-bit example scripts like <i>64Bit.iss</i> have all been updated to use <tt>x64compatible</tt> as preferred.<br/><br/>
+  </li>
+  <li>In 64-bit install mode [Files] section flag <tt>regtypelib</tt> now registers type libraries inside a 64-bit process on Windows 11 for Arm as well.</li>
+  <li>Setup now logs the machine types supported by the system. For example, when running on Windows 11 for Arm it now logs: "Machine types supported by system: x86 x64 arm32 arm64".</li>
+  <li>Message OnlyOnTheseArchitectures is not used anymore. Instead existing message WindowsVersionNotSupported is now shown when Setup is started on an architecture which is not allowed by the <tt>ArchitecturesAllowed</tt> expression. (But please do not remove the message from translation files.)<br/><br/></li>
+  <li>Pascal Scripting change: Add new <tt>IsArm32Compatible</tt>, <tt>IsX64Compatible</tt>, <tt>IsX64OS</tt>, <tt>IsX86Compatible</tt>, and <tt>IsX86OS</tt> support functions. The <tt>IsX64</tt> support function still exists but is now deprecated as explained above. Example testing all platform identifiers:
+      <pre>[Code]
+function InitializeSetup: Boolean;
+begin
+  if IsArm32Compatible then Log('IsArm32Compatible');
+  if IsArm64 then Log('IsArm64');
+  if IsIA64 then Log('IsIA64');
+  if IsX64OS then Log('IsX64OS');
+  if IsX64Compatible then Log('IsX64Compatible');
+  if IsX86 then Log('IsX86');
+  if IsX86OS then Log('IsX86OS');
+  if IsX86Compatible then Log('IsX86Compatible');
+  if IsWin64 then Log('IsWin64');
+  Result := True;
+end;</pre>
+  </li>
+</ul>
 <p><span class="head2">Support for #include files improved</span></p>
 <ul>
   <li>The Compiler IDE now opens up to 20 #include files in tabs, instead of up to 10.</li>