Browse Source

Merge branch 'trustfunc'

Martijn Laan 5 tháng trước cách đây
mục cha
commit
823a86a588

+ 2 - 1
.github/workflows/build.yml

@@ -50,7 +50,8 @@ jobs:
             'tmp-unsigned\iscc /Sissigntool256="${{github.workspace}}\home\bin\run-signtool.bat $f" /DSIGNTOOL setup.iss'
       - name: build issrc
         run: |
-          "set DELPHIXEROOT=$env:DELPHIXEROOT" | Out-File -NoNewline -Encoding ascii compilesettings.bat
+          "set DELPHIXEROOT=$env:DELPHIXEROOT" | Out-File -Encoding ascii compilesettings.bat
+          "set ISSIGTOOL_KEY_FILE=${{github.workspace}}\home\bin\mykey.isprivatekey" | Out-File -NoNewline -Encoding ascii -Append compilesettings.bat
           "set DELPHIXEROOT=$env:DELPHIXEROOT" | Out-File -NoNewline -Encoding ascii ISHelp\ISHelpGen\compilesettings.bat
           "set HHCEXE=%ProgramFiles(x86)%\HTML Help Workshop\hhc.exe" | Out-File -NoNewline -Encoding ascii ISHelp\compilesettings.bat
           .\build.bat

+ 2 - 2
Components/ScintEdit.pas

@@ -858,8 +858,8 @@ end;
 
 procedure TScintEdit.CreateWnd;
 begin
-  if IsscintLibary = 0 then
-    Error('CreateWnd: IsscintLibary is 0');
+  if IsscintLibrary = 0 then
+    Error('CreateWnd: IsscintLibrary is 0');
   inherited;
   FDirectPtr := Pointer(SendMessage(Handle, SCI_GETDIRECTPOINTER, 0, 0));
   if FDirectPtr = nil then

+ 12 - 4
Components/ScintInt.pas

@@ -1353,15 +1353,23 @@ type
   SciFnDirectStatus = function(ptr: Pointer; iMessage: Cardinal;
     wParam: WPARAM; lParam: LPARAM; var Status: Integer): LRESULT; cdecl;
 
+const
+  IsscintDLL = 'isscint.dll';
+
 var
-  IsscintLibary: HMODULE;
+  IsscintLibrary: HMODULE;
+
+procedure InitIsscintLibrary;
 
 implementation
 
 uses
-  PathFunc;
+  PathFunc, TrustFunc;
 
-initialization
-  IsscintLibary := LoadLibrary(PChar(AddBackslash(PathExtractPath(ParamStr(0))) + 'isscint.dll'));
+procedure InitIsscintLibrary;
+begin
+  var FileName := AddBackslash(PathExtractPath(ParamStr(0))) + IsscintDLL;
+  IsscintLibrary := LoadTrustedLibrary(PChar(FileName));
+end;
 
 end.

+ 23 - 0
Components/TrustFunc.AllowedPublicKeys.inc

@@ -0,0 +1,23 @@
+{ Inno Setup build: the second key in this file should be replaced by your
+  own and this will happen automatically when using build.bat or build-ce.bat.
+  To ignore this change consider using Git's assume-unchanged or skip-worktree
+  functionality.
+  
+  Other builds: if you need only one key you can set AllowedPublicKey2Text To
+  an empty string and remove the '//end' marker. }
+
+AllowedPublicKey1Text := '''
+format issig-public-key
+key-id def0147c3bbc17ab99bf7b7a9c2de1390283f38972152418d7c2a4a7d7131a38
+public-x e3e943066aff8f28d2219fd71c9ffff4c8d1aa26bc4225434be67180ab5e242d
+public-y e419041c3f54551e86a1c47f387005cd535dfc9d64339b30d37f9a4f7866b650
+
+''';
+
+AllowedPublicKey2Text := '''
+format issig-public-key
+key-id def020edee3c4835fd54d85eff8b66d4d899b22a777353ca4a114b652e5e7a28
+public-x 515dc7d6c16d4a46272ceb3d158c5630a96466ab4d948e72c2029d737c823097
+public-y f3c21f6b5156c52a35f6f28016ee3e31a3ded60c325b81fb7b1f88c221081a61
+
+''';//end

+ 122 - 0
Components/TrustFunc.pas

@@ -0,0 +1,122 @@
+unit TrustFunc;
+
+{
+  Inno Setup
+  Copyright (C) 1997-2025 Jordan Russell
+  Portions by Martijn Laan
+  For conditions of distribution and use, see LICENSE.TXT.
+
+  Trust support functions using ISSigFunc and key texts from TrustFunc.AllowedPublicKeys.inc
+}
+
+{.$DEFINE TRUSTALL}
+
+interface
+
+procedure CheckFileTrust(const FileName: String; const CheckExists: Boolean = True);
+function LoadTrustedLibrary(const FileName: String; const TrustAllOnDebug: Boolean = False): HMODULE;
+
+implementation
+
+uses
+  Winapi.Windows, System.SysUtils {$IFNDEF TRUSTALL}, System.Classes, ECDSA, SHA256, ISSigFunc {$ENDIF};
+
+procedure CheckFileTrust(const FileName: String; const CheckExists: Boolean);
+begin
+  if CheckExists then begin
+    var Attr := GetFileAttributes(PChar(FileName));
+    if (Attr = INVALID_FILE_ATTRIBUTES) or (Attr and faDirectory <> 0) then
+      raise Exception.CreateFmt('File "%s" does not exist.',
+        [FileName]);
+  end;
+{$IFNDEF TRUSTALL}
+  var AllowedPublicKey1Text, AllowedPublicKey2Text: String;
+  {$I TrustFunc.AllowedPublicKeys.inc}
+  var Key1: TECDSAKey := nil;
+  var Key2: TECDSAKey := nil;
+  try
+    Key1 := TECDSAKey.Create;
+    if ISSigImportKeyText(Key1, AllowedPublicKey1Text, False) <> ikrSuccess then
+      raise Exception.Create('ISSigImportKeyText failed');
+    if AllowedPublicKey2Text <> '' then begin
+      Key2 := TECDSAKey.Create;
+      if ISSigImportKeyText(Key2, AllowedPublicKey2Text, False) <> ikrSuccess then
+        raise Exception.Create('ISSigImportKeyText failed');
+    end;
+
+    var AllowedKeys: array of TECDSAKey;
+    if Key2 <> nil then
+      AllowedKeys := [Key1, Key2]
+    else
+      AllowedKeys := [Key1];
+
+    const SigFileName = FileName + '.issig';
+    const SigText = ISSigLoadTextFromFile(SigFileName);
+
+    var ExpectedFileSize: Int64;
+    var ExpectedFileHash: TSHA256Digest;
+    if ISSigVerifySignatureText(AllowedKeys, SigText, ExpectedFileSize,
+       ExpectedFileHash) <> vsrSuccess then
+      raise Exception.CreateFmt('Signature file "%s" is not valid',
+        [SigFileName]);
+
+    const F = TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+    try
+      if F.Size <> ExpectedFileSize then
+        raise Exception.CreateFmt('File "%s" is not trusted (incorrect size).',
+          [FileName]);
+      if not SHA256DigestsEqual(ISSigCalcStreamHash(F), ExpectedFileHash) then
+        raise Exception.CreateFmt('File "%s" is not trusted (incorrect hash).',
+          [FileName]);
+    finally
+      F.Free;
+    end;
+  finally
+    Key2.Free;
+    Key1.Free;
+  end;
+{$ENDIF}
+end;
+
+function Win32ErrorString(ErrorCode: Integer): String;
+{ Like SysErrorMessage but also passes the FORMAT_MESSAGE_IGNORE_INSERTS flag
+  which allows the function to succeed on errors like 129 }
+var
+  Len: Integer;
+  Buffer: array[0..1023] of Char;
+begin
+  Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
+    FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY, nil,
+    ErrorCode, 0, Buffer, SizeOf(Buffer) div SizeOf(Buffer[0]), nil);
+  while (Len > 0) and ((Buffer[Len-1] <= ' ') or (Buffer[Len-1] = '.')) do
+    Dec(Len);
+  SetString(Result, Buffer, Len);
+end;
+
+function DoLoadLibrary(const FileName: String): HMODULE;
+begin
+  Result := SafeLoadLibrary(PChar(FileName), SEM_NOOPENFILEERRORBOX);
+  if Result = 0 then
+    raise Exception.Create(Win32ErrorString(GetLastError));
+end;
+
+function LoadTrustedLibrary(const FileName: String; const TrustAllOnDebug: Boolean): HMODULE;
+begin
+{$IFDEF DEBUG}
+  if TrustAllOnDebug then begin
+    Result := DoLoadLibrary(FileName);
+    Exit;
+  end;
+{$ENDIF}
+  { First open a temporary regular handle to the library to protect it from changes
+    between the trust check and the load }
+  const F = TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+  try
+    CheckFileTrust(FileName, False);
+    Result := DoLoadLibrary(FileName);
+  finally
+    F.Free;
+  end;
+end;
+
+end.

+ 6 - 0
Files/isbzip.dll.issig

@@ -0,0 +1,6 @@
+format issig-v1
+file-size 39200
+file-hash 8072e83385afc4a84006271a87a11fc0a22b149cbd77322669ca56c470d28ced
+key-id def0147c3bbc17ab99bf7b7a9c2de1390283f38972152418d7c2a4a7d7131a38
+sig-r c5d2720f9be49d87c4800bd8717066613173fae1e26ffb9f31f304a1be40e71e
+sig-s c68f97d069e34e7b2b410222032401254c35641d293ebf3fa0078d19b3478db4

+ 6 - 0
Files/islzma.dll.issig

@@ -0,0 +1,6 @@
+format issig-v1
+file-size 135816
+file-hash b252471e95f0853902b15ae71a90574f9b168f8d4a0c474b20537511f90220a5
+key-id def0147c3bbc17ab99bf7b7a9c2de1390283f38972152418d7c2a4a7d7131a38
+sig-r 63d9a298fdb44394705221a9e65d1fb459d20c73d26aa56cdacf8d0942896b64
+sig-s f7621fc374e28c22f21fcb0ce77acf8a6723c5d0934e6aa0f5a718afeea6cfb3

+ 6 - 0
Files/isscint.dll.issig

@@ -0,0 +1,6 @@
+format issig-v1
+file-size 795776
+file-hash 5ae5dcd47ae9cd0929e0d6b2591e2ecc14cb8dfe4e04fb37a6cef5f1896edd11
+key-id def0147c3bbc17ab99bf7b7a9c2de1390283f38972152418d7c2a4a7d7131a38
+sig-r dd7de5a0ea422c67375023d74c410973a8508a054d6675710a2e591d7b33abdd
+sig-s 0bd08ccdb7f69a97b3e390a28dfdda98a1cad50f11682567fa03b93c7c5fb285

+ 6 - 0
Files/iszlib.dll.issig

@@ -0,0 +1,6 @@
+format issig-v1
+file-size 34592
+file-hash 14c0d4a2a41572384f8309cdf03de5c6e7ed46bef64cce70d989b2665eff1a47
+key-id def0147c3bbc17ab99bf7b7a9c2de1390283f38972152418d7c2a4a7d7131a38
+sig-r e245c707db5d1f1d3f47226aa3923e0240e23abb8fa5077eb4fb7ffc776a89ff
+sig-s bf84dbda5c76cce509931aa05bdd9992f96154f9493345e7f1669e169f0b810c

+ 10 - 7
ISHelp/ISHelpGen/ISHelpGen.dpr

@@ -5,6 +5,7 @@ program ISHelpGen;
 uses
   Windows,
   SysUtils,
+  StrUtils,
   Classes,
   ActiveX,
   ComObj,
@@ -331,7 +332,8 @@ begin
   Result := '';
   Node := Node.FirstChild;
   while Assigned(Node) do begin
-    case ElementFromNode(Node) of
+    var Element := ElementFromNode(Node);
+    case Element of
       el_Text:
         Result := Result + EscapeHTML(Node.Text, False);
       elA:
@@ -354,12 +356,13 @@ begin
         Result := Result + '<dl>' + ParseFormattedText(Node) + '</dl>';
       elDT:
         Result := Result + '<dt>' + ParseFormattedText(Node) + '</dt>';
-      elExample:
-        Result := Result + '<div class="examplebox">' + SNewLine +
-          '<div class="exampleheader">Example:</div>' + ParseFormattedText(Node) + '</div>';
-      elExamples:
-        Result := Result + '<div class="examplebox">' + SNewLine +
-          '<div class="exampleheader">Examples:</div>' + ParseFormattedText(Node) + '</div>';
+      elExample, elExamples:
+        begin
+          Result := Result + '<div class="examplebox">' + SNewLine;
+          if Node.OptionalAttributes['noheader'] <> '1' then
+            Result := Result + '<div class="exampleheader">Example' + IfThen(Element = elExamples, 's', '') + ':</div>';
+          Result := Result + ParseFormattedText(Node) + '</div>';
+        end;
       elFlag:
         begin
           S := Node.Attributes['name'];

+ 2 - 0
ISHelp/isetup.dtd

@@ -65,7 +65,9 @@
 <!ELEMENT pre %Inline;>
 <!ELEMENT precode %Inline;>
 <!ELEMENT example %InlineOrBlock;>
+<!ATTLIST example noheader CDATA #IMPLIED>
 <!ELEMENT examples %InlineOrBlock;>
+<!ATTLIST examples noheader CDATA #IMPLIED>
 <!ELEMENT indent %Block;>
 
 <!-- Fancier block elements -->

+ 95 - 4
ISHelp/isetup.xml

@@ -86,6 +86,7 @@
     <contentstopic title="Uninstaller Exit Codes" topic="uninstexitcodes" />
     <contentstopic title="Compiler IDE Keyboard And Mouse Commands" topic="compformshortcuts" />
     <contentstopic title="Compiler IDE Regular Expressions" topic="compformregex" />
+    <contentstopic title="Inno Setup Signature Tool" topic="issigtool" />
     <contentstopic title="Miscellaneous Notes" topic="technotes" />
     <contentstopic title="Example Scripts" topic="examples" />
     <contentstopic title="Frequently Asked Questions" topic="faq" />
@@ -102,7 +103,7 @@
 <body>
 
 <p>
-<b>Inno Setup version 6.4.2</b><br/>
+<b>Inno Setup version 6.4.3-dev</b><br/>
 <b>Copyright &copy; 1997-2025 Jordan Russell. All rights reserved.</b><br/>
 <b>Portions Copyright &copy; 2000-2025 Martijn Laan. All rights reserved.</b><br/>
 <extlink href="https://jrsoftware.org/">Inno Setup home page</extlink>
@@ -2955,7 +2956,7 @@ Shown by default, but can be disabled in some cases via <link topic="setup_disab
 
 <p>All entries are processed by the installer in the order they appear in a section.</p>
 
-<p>You can see the order yourself by loading a script into the Compiler IDE and pressing F7 (Step Into) repeatedly: each time Setup or Uninstall is about to process an entry the IDE will pause Setup or Uninstall and show you the entry.</p> 
+<p>You can see the order yourself by loading a script into the Compiler IDE and pressing F7 (Step Into) repeatedly: each time Setup or Uninstall is about to process an entry the IDE will pause Setup or Uninstall and show you the entry.</p>
 
 <p>Changes are undone by the uninstaller in the <i>opposite</i> order in which the installer made them. This is because the uninstall log is parsed from end to beginning.</p>
 
@@ -3136,7 +3137,7 @@ Filename: "{win}\MYPROG.INI"; Section: "InstallSettings"; Key: "InstallPath"; St
 
 <p>A single dash (-) means there's no shortcut available for this command in the key map.</p>
 
-<p>Note: a few of the shortcuts below use string representations for special virtual keys. More precisely: ; for VK_OEM_1, . for VK_OEM_PERIOD, / for VK_OEM_2, [ for VK_OEM_4, \ for VK_OEM_5, and ] for VK_OEM_6. Different keyboard layouts usually reposition these special virtual keys or change the characters produced when they are pressed. In the <i>Edit</i> menu these shortcuts are shown using the current system's keyboard layout. For example, when using a French AZERTY keyboard layout the <i>Toggle Line Comment</i> shortcut is shown as Ctrl+: instead of Ctrl+/. If the keyboard layout doesn't support the virtual key then no shortcut will be shown.</p> 
+<p>Note: a few of the shortcuts below use string representations for special virtual keys. More precisely: ; for VK_OEM_1, . for VK_OEM_PERIOD, / for VK_OEM_2, [ for VK_OEM_4, \ for VK_OEM_5, and ] for VK_OEM_6. Different keyboard layouts usually reposition these special virtual keys or change the characters produced when they are pressed. In the <i>Edit</i> menu these shortcuts are shown using the current system's keyboard layout. For example, when using a French AZERTY keyboard layout the <i>Toggle Line Comment</i> shortcut is shown as Ctrl+: instead of Ctrl+/. If the keyboard layout doesn't support the virtual key then no shortcut will be shown.</p>
 
 <table>
 <tr><td></td><td><u>Classic</u></td><td><u>Visual Studio Code</u></td></tr>
@@ -3492,6 +3493,96 @@ Filename: "{win}\MYPROG.INI"; Section: "InstallSettings"; Key: "InstallPath"; St
 
 
 
+<topic name="issigtool" title="Inno Setup Signature Tool">
+<keyword value="ISSigTool" />
+<body>
+
+<p>Inno Setup includes a command-line tool, ISSigTool.exe. This tool is designed to sign files using cryptographic signatures.</p>
+
+<p>Note: ISSigTool.exe does not replace Microsoft's signtool.exe in any way and is in fact not related to Authenticode Code Signing at all. If you are looking for more information about this topic see <link topic="setup_signtool">SignTool</link> instead.</p>
+
+<p>Command line usage is as follows:</p>
+
+<indent>
+<p>issigtool <i>[options]</i> <i>&lt;command&gt;</i> <i>&lt;arguments&gt;</i></p>
+</indent>
+
+<p>Available commands:</p>
+
+<indent>
+<table>
+<tr>
+<td>sign <i>&lt;file names&gt;</i></td>
+<td>Signs each specified file. Requires a private key.</td>
+</tr>
+<tr>
+<td>verify <i>&lt;file names&gt;</i></td>
+<td>Verifies the signature of each specified file against the key.</td>
+</tr>
+<tr>
+<td>export-public-key <i>&lt;file name&gt;</i></td>
+<td>Exports the public key used in the signing process to the specified file.</td>
+</tr>
+<tr>
+<td>generate-private-key</td>
+<td>Generates a new private key for signing operations.</td>
+</tr>
+</table>
+</indent>
+
+<p>Valid options are:</p>
+
+<indent>
+<table>
+<tr>
+<td>--key-file=&lt;filename&gt;</td>
+<td>Specifies the private key filename required for signing. This option overriddes the <tt>ISSIGTOOL_KEY_FILE</tt> environment variable which can also be used.</td>
+</tr>
+</table>
+</indent>
+
+<p>Examples:</p>
+
+<indent>
+<examples noheader="1">
+issigtool --key-file=MyKey.isprivatekey generate-private-key<br/>
+issigtool --key-file=MyKey.isprivatekey sign MyProg.dll<br/>
+issigtool --key-file=MyKey.isprivatekey export-public-key MyKey.ispublickey<br/>
+issigtool --key-file=MyKey.ispublickey verify MyProg.dll
+</examples>
+</indent>
+
+<p>Exit codes:</p>
+
+<indent>
+<table>
+<tr>
+<td>0</td>
+<td>Success</td>
+</tr>
+<tr>
+<td>1</td>
+<td>A signature verification failed</td>
+</tr>
+<tr>
+<td>2</td>
+<td>Command line parameters were invalid or a fatal error occurred</td>
+</tr>
+</table>
+</indent>
+
+<p>Notes:</p>
+
+<ul>
+<li>Filenames that include spaces must be enclosed in quotes.</li>
+<li>Ensure the private key file is secure, as its compromise can affect the validity of your signatures.</li>
+</ul>
+
+</body>
+</topic>
+
+
+
 <topic name="setupcmdline" title="Setup Command Line Parameters">
 <keyword value="Setup Command Line Parameters" />
 <keyword value="command line parameters" />
@@ -5665,7 +5756,7 @@ SignTool=mycustom sign /a /n $qMy Common Name$q /as /fd sha256 /td sha256 /tr ht
 <p>Note: for security reasons you should give a unique name to any Sign Tool set to <tt>$p</tt>, and not use a <tt>byparam</tt> name copied from this example. Consider what happens if you #include a third-party file that says:</p>
 <pre>
 [Setup]
-SignTool=byparam format c: 
+SignTool=byparam format c:
 </pre>
 </example>
 <p>Further details on obtaining signing certificates and using code-signing tools are beyond the scope of this documentation.</p>

+ 4 - 0
Projects/Bin/synch-isfiles.bat

@@ -7,9 +7,13 @@ echo - Synching files from Files to Projects\Bin
 copy ..\..\Files\Default.isl
 copy ..\..\Files\ISPPBuiltins.iss
 copy ..\..\Files\is*zip.dll
+copy ..\..\Files\isbzip.dll.issig
 copy ..\..\Files\is*zlib.dll
+copy ..\..\Files\iszlib.dll.issig
 copy ..\..\Files\isscint.dll
+copy ..\..\Files\isscint.dll.issig
 copy ..\..\Files\islzma.dll
+copy ..\..\Files\islzma.dll.issig
 copy ..\..\Files\islzma*.exe
 copy ..\..\Files\ISetup.chm
 copy ..\..\Files\ISetup-dark.chm

+ 28 - 1
Projects/Compil32.dpr

@@ -15,12 +15,14 @@ uses
   SysUtils,
   Forms,
   PathFunc in '..\Components\PathFunc.pas',
+  TrustFunc in '..\Components\TrustFunc.pas',
   IDE.MainForm in 'Src\IDE.MainForm.pas' {MainForm},
   Shared.CommonFunc.Vcl in 'Src\Shared.CommonFunc.Vcl.pas',
   Shared.CommonFunc in 'Src\Shared.CommonFunc.pas',
   IDE.HelperFunc in 'Src\IDE.HelperFunc.pas',
   IDE.Messages in 'Src\IDE.Messages.pas',
   Shared.CompilerInt in 'Src\Shared.CompilerInt.pas',
+  Shared.CompilerInt.Struct in 'Src\Shared.CompilerInt.Struct.pas',
   IDE.OptionsForm in 'Src\IDE.OptionsForm.pas' {OptionsForm},
   IDE.StartupForm in 'Src\IDE.StartupForm.pas' {StartupForm},
   IDE.Wizard.WizardForm in 'Src\IDE.Wizard.WizardForm.pas' {WizardForm},
@@ -67,7 +69,10 @@ uses
   SHA256 in '..\Components\SHA256.pas',
   Shared.DotNetVersion in 'Src\Shared.DotNetVersion.pas',
   isxclasses_wordlists_generated in '..\ISHelp\isxclasses_wordlists_generated.pas',
-  IDE.ImagesModule in 'Src\IDE.ImagesModule.pas' {ImagesModule: TDataModule};
+  IDE.ImagesModule in 'Src\IDE.ImagesModule.pas' {ImagesModule: TDataModule},
+  ECDSA in '..\Components\ECDSA.pas',
+  ISSigFunc in '..\Components\ISSigFunc.pas',
+  StringScanner in '..\Components\StringScanner.pas';
 
 {$SETPEOSVERSION 6.1}
 {$SETPESUBSYSVERSION 6.1}
@@ -200,6 +205,28 @@ begin
 end;
 
 begin
+  {$IFNDEF STATICCOMPILER}
+  try
+    InitISCmplrLibrary;
+  except
+    begin
+      MessageBox(0, PChar(Format('Could not load %s: %s' {$IFDEF DEBUG} + #13#10#13#10'Did you build the ISCmplr project?' {$ENDIF},
+        [ISCmplrDLL, GetExceptMessage])), nil, MB_OK or MB_ICONSTOP);
+      Halt(3);
+    end;
+  end;
+  {$ENDIF}
+
+  try
+    InitIsscintLibrary;
+  except
+    begin
+      MessageBox(0, PChar(Format('Could not load %s: %s' {$IFDEF DEBUG} + #13#10#13#10'Did you run Projects\Bin\synch-isfiles.bat as instructed in README.md?' {$ENDIF},
+        [IsscintDLL, GetExceptMessage])), nil, MB_OK or MB_ICONSTOP);
+      Halt(4);
+    end;
+  end;
+
   {$IFDEF DEBUG}
   ReportMemoryLeaksOnShutdown := True;
   {$ENDIF}

+ 5 - 0
Projects/Compil32.dproj

@@ -78,6 +78,7 @@
         </DelphiCompile>
         <DCCReference Include="..\Components\SafeDLLPath.pas"/>
         <DCCReference Include="..\Components\PathFunc.pas"/>
+        <DCCReference Include="..\Components\TrustFunc.pas"/>
         <DCCReference Include="Src\IDE.MainForm.pas">
             <Form>MainForm</Form>
         </DCCReference>
@@ -86,6 +87,7 @@
         <DCCReference Include="Src\IDE.HelperFunc.pas"/>
         <DCCReference Include="Src\IDE.Messages.pas"/>
         <DCCReference Include="Src\Shared.CompilerInt.pas"/>
+        <DCCReference Include="Src\Shared.CompilerInt.Struct.pas"/>
         <DCCReference Include="Src\IDE.OptionsForm.pas">
             <Form>OptionsForm</Form>
         </DCCReference>
@@ -153,6 +155,9 @@
             <FormType>dfm</FormType>
             <DesignClass>TDataModule</DesignClass>
         </DCCReference>
+        <DCCReference Include="..\Components\ECDSA.pas"/>
+        <DCCReference Include="..\Components\ISSigFunc.pas"/>
+        <DCCReference Include="..\Components\StringScanner.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

+ 21 - 2
Projects/ISCC.dpr

@@ -23,12 +23,18 @@ uses
   Classes,
   {$IFDEF STATICCOMPILER} Compiler.Compile, {$ENDIF}
   PathFunc in '..\Components\PathFunc.pas',
+  TrustFunc in '..\Components\TrustFunc.pas',
   Shared.CommonFunc in 'Src\Shared.CommonFunc.pas',
   Shared.CompilerInt in 'Src\Shared.CompilerInt.pas',
+  Shared.CompilerInt.Struct in 'Src\Shared.CompilerInt.Struct.pas',
   Shared.FileClass in 'Src\Shared.FileClass.pas',
   Shared.ConfigIniFile in 'Src\Shared.ConfigIniFile.pas',
   Shared.SignToolsFunc in 'Src\Shared.SignToolsFunc.pas',
-  Shared.Int64Em in 'Src\Shared.Int64Em.pas';
+  Shared.Int64Em in 'Src\Shared.Int64Em.pas',
+  SHA256 in '..\Components\SHA256.pas',
+  ECDSA in '..\Components\ECDSA.pas',
+  ISSigFunc in '..\Components\ISSigFunc.pas',
+  StringScanner in '..\Components\StringScanner.pas';
 
 {$SETPEOSVERSION 6.1}
 {$SETPESUBSYSVERSION 6.1}
@@ -559,6 +565,14 @@ begin
   end;
 
   {$IFNDEF STATICCOMPILER}
+  try
+    InitISCmplrLibrary;
+  except
+    begin
+      WriteStdErr(Format('Could not load %s: %s', [ISCmplrDLL, GetExceptMessage]), True);
+      Halt(1);
+    end;
+  end;
   Ver := ISDllGetVersion;
   {$ELSE}
   Ver := ISGetVersion;
@@ -643,6 +657,11 @@ begin
     Halt(ExitCode);
 end;
 
+function ISPPInstalled: Boolean;
+begin
+  Result := NewFileExists(PathExtractPath(NewParamStr(0)) + 'ISPP.dll');
+end;
+
 begin
   SignTools := TStringList.Create;
   try
@@ -653,7 +672,7 @@ begin
     StdErrHandleIsConsole := GetConsoleMode(StdErrHandle, Mode);
     SetConsoleCtrlHandler(@ConsoleCtrlHandler, True);
     try
-      IsppMode := FileExists(ExtractFilePath(NewParamStr(0)) + 'ispp.dll');
+      IsppMode := ISPPInstalled;
       ProcessCommandLine;
       Go;
     except

+ 6 - 0
Projects/ISCC.dproj

@@ -77,12 +77,18 @@
         </DelphiCompile>
         <DCCReference Include="..\Components\SafeDLLPath.pas"/>
         <DCCReference Include="..\Components\PathFunc.pas"/>
+        <DCCReference Include="..\Components\TrustFunc.pas"/>
         <DCCReference Include="Src\Shared.CommonFunc.pas"/>
         <DCCReference Include="Src\Shared.CompilerInt.pas"/>
+        <DCCReference Include="Src\Shared.CompilerInt.Struct.pas"/>
         <DCCReference Include="Src\Shared.FileClass.pas"/>
         <DCCReference Include="Src\Shared.ConfigIniFile.pas"/>
         <DCCReference Include="Src\Shared.SignToolsFunc.pas"/>
         <DCCReference Include="Src\Shared.Int64Em.pas"/>
+        <DCCReference Include="..\Components\SHA256.pas"/>
+        <DCCReference Include="..\Components\ECDSA.pas"/>
+        <DCCReference Include="..\Components\ISSigFunc.pas"/>
+        <DCCReference Include="..\Components\StringScanner.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

+ 6 - 2
Projects/ISCmplr.dpr

@@ -12,7 +12,7 @@ library ISCmplr;
 uses
   SafeDLLPath in '..\Components\SafeDLLPath.pas',
   SysUtils,
-  Shared.CompilerInt in 'Src\Shared.CompilerInt.pas',
+  Shared.CompilerInt.Struct in 'Src\Shared.CompilerInt.Struct.pas',
   Shared.PreprocInt in 'Src\Shared.PreprocInt.pas',
   Compiler.Compile in 'Src\Compiler.Compile.pas',
   Compiler.SetupCompiler in 'Src\Compiler.SetupCompiler.pas',
@@ -36,6 +36,7 @@ uses
   ChaCha20 in '..\Components\ChaCha20.pas',
   Shared.VerInfoFunc in 'Src\Shared.VerInfoFunc.pas',
   PathFunc in '..\Components\PathFunc.pas',
+  TrustFunc in '..\Components\TrustFunc.pas',
   Shared.CommonFunc in 'Src\Shared.CommonFunc.pas',
   Shared.Int64Em in 'Src\Shared.Int64Em.pas',
   SHA256 in '..\Components\SHA256.pas',
@@ -48,7 +49,10 @@ uses
   Shared.SetupSteps in 'Src\Shared.SetupSteps.pas',
   SimpleExpression in '..\Components\SimpleExpression.pas',
   Shared.DotNetVersion in 'Src\Shared.DotNetVersion.pas',
-  PBKDF2 in '..\Components\PBKDF2.pas';
+  PBKDF2 in '..\Components\PBKDF2.pas',
+  ECDSA in '..\Components\ECDSA.pas',
+  ISSigFunc in '..\Components\ISSigFunc.pas',
+  StringScanner in '..\Components\StringScanner.pas';
 
 {$IMAGEBASE $00800000}
 {$SETPEOSVERSION 6.1}

+ 5 - 1
Projects/ISCmplr.dproj

@@ -79,7 +79,7 @@
             <MainSource>MainSource</MainSource>
         </DelphiCompile>
         <DCCReference Include="..\Components\SafeDLLPath.pas"/>
-        <DCCReference Include="Src\Shared.CompilerInt.pas"/>
+        <DCCReference Include="Src\Shared.CompilerInt.Struct.pas"/>
         <DCCReference Include="Src\Shared.PreprocInt.pas"/>
         <DCCReference Include="Src\Compiler.Compile.pas"/>
         <DCCReference Include="Src\Compiler.SetupCompiler.pas"/>
@@ -103,6 +103,7 @@
         <DCCReference Include="..\Components\ChaCha20.pas"/>
         <DCCReference Include="Src\Shared.VerInfoFunc.pas"/>
         <DCCReference Include="..\Components\PathFunc.pas"/>
+        <DCCReference Include="..\Components\TrustFunc.pas"/>
         <DCCReference Include="Src\Shared.CommonFunc.pas"/>
         <DCCReference Include="Src\Shared.Int64Em.pas"/>
         <DCCReference Include="..\Components\SHA256.pas"/>
@@ -116,6 +117,9 @@
         <DCCReference Include="..\Components\SimpleExpression.pas"/>
         <DCCReference Include="Src\Shared.DotNetVersion.pas"/>
         <DCCReference Include="..\Components\PBKDF2.pas"/>
+        <DCCReference Include="..\Components\ECDSA.pas"/>
+        <DCCReference Include="..\Components\ISSigFunc.pas"/>
+        <DCCReference Include="..\Components\StringScanner.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

+ 1 - 1
Projects/ISSigTool.dpr

@@ -232,7 +232,7 @@ end;
 
 procedure ShowBanner;
 begin
-  Writeln('Inno Setup Command-Line Signature Tool');
+  Writeln('Inno Setup Signature Tool');
   Writeln('Copyright (C) 1997-2025 Jordan Russell. All rights reserved.');
   Writeln('Portions Copyright (C) 2000-2025 Martijn Laan. All rights reserved.');
   Writeln('https://www.innosetup.com');

BIN
Projects/Res/ISSigTool.versionandicon.res


+ 1 - 1
Projects/Src/Compiler.Compile.pas

@@ -12,7 +12,7 @@ unit Compiler.Compile;
 interface
 
 uses
-  Shared.CompilerInt;
+  Shared.CompilerInt.Struct;
 
 function ISCompileScript(const Params: TCompileScriptParamsEx;
   const PropagateExceptions: Boolean): Integer;

+ 25 - 35
Projects/Src/Compiler.SetupCompiler.pas

@@ -20,7 +20,7 @@ interface
 uses
   Windows, SysUtils, Classes, Generics.Collections,
   SimpleExpression, SHA256, ChaCha20,
-  Shared.Struct, Shared.CompilerInt, Shared.PreprocInt, Shared.SetupMessageIDs,
+  Shared.Struct, Shared.CompilerInt.Struct, Shared.PreprocInt, Shared.SetupMessageIDs,
   Shared.SetupSectionDirectives, Shared.VerInfoFunc, Shared.Int64Em, Shared.DebugStruct,
   Compiler.ScriptCompiler, Compiler.StringLists, Compression.LZMACompressor;
 
@@ -288,7 +288,7 @@ implementation
 
 uses
   Commctrl, TypInfo, AnsiStrings, Math, WideStrUtils,
-  PathFunc, Shared.CommonFunc, Compiler.Messages, Shared.SetupEntFunc,
+  PathFunc, TrustFunc, Shared.CommonFunc, Compiler.Messages, Shared.SetupEntFunc,
   Shared.FileClass, Compression.Base, Compression.Zlib, Compression.bzlib,
   Shared.LangOptionsSectionDirectives, Shared.ResUpdateFunc, Compiler.ExeUpdateFunc,
 {$IFDEF STATICPREPROC}
@@ -502,31 +502,30 @@ begin
   end;
 end;
 
+function LoadCompilerDLL(const Filename: String; const TrustAllOnDebug: Boolean = False): HMODULE;
+begin
+  try
+    Result := LoadTrustedLibrary(FileName, TrustAllOnDebug);
+  except
+    begin
+      TSetupCompiler.AbortCompileFmt('Failed to load %s: %s', [PathExtractName(Filename), GetExceptMessage]);
+      Result := 0; //silence compiler
+    end;
+  end;
+end;
+
 procedure TSetupCompiler.InitPreprocessor;
-{$IFNDEF STATICPREPROC}
-var
-  Filename: String;
-  Attr: DWORD;
-  M: HMODULE;
-{$ENDIF}
 begin
   if PreprocessorInitialized then
     Exit;
 {$IFNDEF STATICPREPROC}
-  Filename := CompilerDir + 'ISPP.dll';
-  Attr := GetFileAttributes(PChar(Filename));
-  if (Attr = INVALID_FILE_ATTRIBUTES) and (GetLastError = ERROR_FILE_NOT_FOUND) then begin
-    { ISPP unavailable; fall back to built-in preprocessor }
-  end
-  else begin
-    M := SafeLoadLibrary(Filename, SEM_NOOPENFILEERRORBOX);
-    if M = 0 then
-      AbortCompileFmt('Failed to load preprocessor DLL "%s" (%d)',
-        [Filename, GetLastError]);
+  var Filename := CompilerDir + 'ISPP.dll';
+  if NewFileExists(Filename) then begin
+    var M := LoadCompilerDLL(Filename, True);
     PreprocessScriptProc := GetProcAddress(M, 'ISPreprocessScriptW');
     if not Assigned(PreprocessScriptProc) then
-      AbortCompileFmt('Failed to get address of functions in "%s"', [Filename]);
-  end;
+      AbortCompile('Failed to get address of functions in ISPP.dll');
+  end; { else ISPP unavailable; fall back to built-in preprocessor }
 {$ELSE}
   PreprocessScriptProc := ISPreprocessScript;
 {$ENDIF}
@@ -534,42 +533,33 @@ begin
 end;
 
 procedure TSetupCompiler.InitZipDLL;
-var
-  M: HMODULE;
 begin
   if ZipInitialized then
     Exit;
-  M := SafeLoadLibrary(CompilerDir + 'iszlib.dll', SEM_NOOPENFILEERRORBOX);
-  if M = 0 then
-    AbortCompileFmt('Failed to load iszlib.dll (%d)', [GetLastError]);
+  var Filename := CompilerDir + 'iszlib.dll';
+  var M := LoadCompilerDLL(Filename);
   if not ZlibInitCompressFunctions(M) then
     AbortCompile('Failed to get address of functions in iszlib.dll');
   ZipInitialized := True;
 end;
 
 procedure TSetupCompiler.InitBzipDLL;
-var
-  M: HMODULE;
 begin
   if BzipInitialized then
     Exit;
-  M := SafeLoadLibrary(CompilerDir + 'isbzip.dll', SEM_NOOPENFILEERRORBOX);
-  if M = 0 then
-    AbortCompileFmt('Failed to load isbzip.dll (%d)', [GetLastError]);
+  var Filename := CompilerDir + 'isbzip.dll';
+  var M := LoadCompilerDLL(Filename);
   if not BZInitCompressFunctions(M) then
     AbortCompile('Failed to get address of functions in isbzip.dll');
   BzipInitialized := True;
 end;
 
 procedure TSetupCompiler.InitLZMADLL;
-var
-  M: HMODULE;
 begin
   if LZMAInitialized then
     Exit;
-  M := SafeLoadLibrary(CompilerDir + 'islzma.dll', SEM_NOOPENFILEERRORBOX);
-  if M = 0 then
-    AbortCompileFmt('Failed to load islzma.dll (%d)', [GetLastError]);
+  var Filename := CompilerDir + 'islzma.dll';
+  var M := LoadCompilerDLL(Filename);
   if not LZMAInitCompressFunctions(M) then
     AbortCompile('Failed to get address of functions in islzma.dll');
   LZMAInitialized := True;

+ 3 - 2
Projects/Src/IDE.MainForm.pas

@@ -25,7 +25,7 @@ uses
   Windows, Messages, SysUtils, Classes, Contnrs, Graphics, Controls, Forms, Dialogs, CommDlg,
   Generics.Collections, UIStateForm, StdCtrls, ExtCtrls, Menus, Buttons, ComCtrls, CommCtrl,
   ScintInt, ScintEdit, IDE.ScintStylerInnoSetup, NewTabSet, ModernColors, IDE.IDEScintEdit,
-  Shared.DebugStruct, Shared.CompilerInt, NewUxTheme, ImageList, ImgList, ToolWin, IDE.HelperFunc,
+  Shared.DebugStruct, Shared.CompilerInt.Struct, NewUxTheme, ImageList, ImgList, ToolWin, IDE.HelperFunc,
   VirtualImageList, BaseImageCollection;
 
 const
@@ -681,7 +681,8 @@ uses
   {$IFDEF STATICCOMPILER} Compiler.Compile, {$ENDIF}
   IDE.OptionsForm, IDE.StartupForm, IDE.Wizard.WizardForm, IDE.SignToolsForm,
   Shared.ConfigIniFile, Shared.SignToolsFunc, IDE.InputQueryComboForm, IDE.MsgBoxDesignerForm,
-  IDE.FilesDesignerForm, IDE.RegistryDesignerForm, IDE.Wizard.WizardFormRegistryHelper;
+  IDE.FilesDesignerForm, IDE.RegistryDesignerForm, IDE.Wizard.WizardFormRegistryHelper,
+  Shared.CompilerInt;
 
 {$R *.DFM}
 

+ 165 - 0
Projects/Src/Shared.CompilerInt.Struct.pas

@@ -0,0 +1,165 @@
+unit Shared.CompilerInt.Struct;
+
+{
+  Inno Setup
+  Copyright (C) 1997-2024 Jordan Russell
+  Portions by Martijn Laan
+  For conditions of distribution and use, see LICENSE.TXT.
+
+  Compiler interface records and other types
+}
+
+interface
+
+uses
+  Windows;
+
+const
+  { Constants passed in Code parameter of callback function }
+  iscbReadScript = 1;      { Sent when compiler needs the next script line }
+  iscbNotifyStatus = 2;    { Sent to notify the application of compiler status }
+  iscbNotifyIdle = 3;      { Sent at various intervals during the compilation }
+  iscbNotifySuccess = 4;   { Sent when compilation succeeds }
+  iscbNotifyError = 5;     { Sent when compilation fails or is aborted by the
+                             application }
+  iscbNotifyPreproc = 6;   { Sent to notify the application of preprocessor results }
+
+  { Return values for callback function }
+  iscrSuccess = 0;         { Return this for compiler to continue }
+  iscrRequestAbort = 1;    { Return this to abort compilation immediately.
+                             (When this value is returned, it is not necessary
+                             to set any of the "out" fields in the
+                             TCompilerCallbackData; the compiler will ignore
+                             them.) }
+
+  { Return values for ISDllCompileScript }
+  isceNoError = 0;         { Successful }
+  isceInvalidParam = 1;    { Bad parameters passed to function }
+  isceCompileFailure = 2;  { There was an error compiling or it was aborted
+                             by the application }
+
+type
+  { TCompilerCallbackData is a record passed to the callback function. The
+    fields which you may access vary depending on what Code was passed to the
+    callback function. }
+  TCompilerCallbackData = record
+    case Integer of
+      iscbReadScript: (
+        Reset: BOOL;          { [in] This field can be ignored in compiler
+                                versions 3.0.1 and later. (Previous versions
+                                of the compiler made multiple passes over the
+                                script, and set Reset to True when it needed
+                                to return to the beginning.) }
+        LineRead: PChar);     { [out] Application returns pointer to the next
+                                line it reads, or a NULL pointer if the end of
+                                file is reached. Application is responsible for
+                                allocating a buffer to hold the line; LineRead
+                                is initially NULL when the callback function
+                                is called. The pointer only needs to remain
+                                valid until the next time the callback function
+                                is called (i.e. the application may return the
+                                same pointer each time). }
+
+      iscbNotifyStatus: (
+        StatusMsg: PChar;     { [in] Contents of status message. }
+        Warning: BOOL);       { [in] Warning indicator (new in 6.0.0) }
+
+      iscbNotifyIdle: (
+        CompressProgress: Cardinal;     { [in] Amount compressed so far
+                                          (new in 4.1.6) }
+        CompressProgressMax: Cardinal;  { [in] Maximum value of CompressProgress
+                                          (new in 4.1.6) }
+        SecondsRemaining: Integer;      { [in] Estimated time remaining, or -1
+                                          if not known (new in 5.1.13) }
+        BytesCompressedPerSecond: Cardinal); { [in] Average bytes compressed
+                                               per second (new in 5.1.13) }
+
+      iscbNotifyPreproc: (
+        PreprocessedScript: PChar; { [in] Preprocessed script (new in 6.1.0) }
+        IncludedFilenames: PChar); { [in] Names of #included files. Each name is
+                                          a null-terminated string, and the final
+                                          name is followed by an additional null
+                                          character (new in 6.1.0) }
+
+      iscbNotifySuccess: (
+        OutputExeFilename: PChar;  { [in] The name of the resulting setup.exe,
+                                          or empty if output was disabled
+                                          (latter new in 5.5.5) }
+        DebugInfo: Pointer;        { [in] Debug info (new in 3.0.0.1) }
+        DebugInfoSize: Cardinal);  { [in] Size of debug info (new in 3.0.0.1) }
+
+      iscbNotifyError: (
+        ErrorMsg: PChar;      { [in] The error message, or NULL if compilation
+                                was aborted by the application. }
+        ErrorFilename: PChar; { [in] Filename in which the error occurred. This
+                                is NULL if the file is the main script. }
+        ErrorLine: Integer);  { [in] The line number the error occurred on.
+                                Zero if the error doesn't apply to any
+                                particular line. }
+  end;
+
+  TCompilerCallbackProc = function(Code: Integer;
+    var Data: TCompilerCallbackData; AppData: Longint): Integer; stdcall;
+
+  PCompileScriptParamsEx = ^TCompileScriptParamsEx;
+  TCompileScriptParamsEx = record
+    Size: Cardinal;       { [in] Set to SizeOf(TCompileScriptParamsEx). }
+    CompilerPath: PChar;  { [in] The "compiler:" directory. This is the
+                            directory which contains the *.e32 files. If this
+                            is set to NULL, the compiler will use the directory
+                            containing the compiler DLL/EXE. }
+    SourcePath: PChar;    { [in] The default source directory, and directory to
+                            look in for #include files. Normally, this is
+                            the directory containing the script file. This
+                            cannot be NULL. }
+    CallbackProc: TCompilerCallbackProc;
+                          { [in] The callback procedure which the compiler calls
+                            to read the script and for status notification. }
+    AppData: Longint;     { [in] Application-defined. AppData is passed to the
+                            callback function. }
+    Options: PChar;       { [in] Additional options. Each option is a
+                            null-terminated string, and the final option is
+                            followed by an additional null character.
+                            If you do not wish to specify any options, set this
+                            field to NULL or to point to a single null
+                            character.
+
+                            Currently supported options:
+
+                            Output=(0|no|false|1|yes|true)
+                              Enables or disables output.
+                            OutputBaseFilename=[filename]
+                              Overrides any OutputBaseFilename setting in the
+                              script; causes the compiler to use [filename]
+                              instead.
+                            OutputDir=[path]
+                              Overrides any output directory in the script;
+                              causes the compiler to use [path] instead.
+                            SignTool-[name]=[command]
+                              Configures a SignTool with name [name] and command
+                              [command].
+                            ISPP:[isppoption]
+                              Configures an ISPP option. }
+  end;
+
+  { The old TCompileScriptParams record. Use this in place of
+    TCompileScriptParamsEx if you need call ISCmplr.dll versions below
+    5.0.5. It's the same except it lacks an Options field. }
+  TCompileScriptParams = record
+    Size: Cardinal;       { [in] Set to SizeOf(TCompileScriptParams). }
+    CompilerPath: PChar;
+    SourcePath: PChar;
+    CallbackProc: TCompilerCallbackProc;
+    AppData: Longint;
+  end;
+
+  PCompilerVersionInfo = ^TCompilerVersionInfo;
+  TCompilerVersionInfo = record
+    Title: PAnsiChar;      { Name of compiler engine - 'Inno Setup' }
+    Version: PAnsiChar;    { Version number text }
+    BinVersion: Cardinal;  { Version number as an integer }
+  end;
+
+implementation
+
+end.

+ 29 - 150
Projects/Src/Shared.CompilerInt.pas

@@ -12,167 +12,46 @@ unit Shared.CompilerInt;
 interface
 
 uses
-  Windows;
-
-const
-  { Constants passed in Code parameter of callback function }
-  iscbReadScript = 1;      { Sent when compiler needs the next script line }
-  iscbNotifyStatus = 2;    { Sent to notify the application of compiler status }
-  iscbNotifyIdle = 3;      { Sent at various intervals during the compilation }
-  iscbNotifySuccess = 4;   { Sent when compilation succeeds }
-  iscbNotifyError = 5;     { Sent when compilation fails or is aborted by the
-                             application }
-  iscbNotifyPreproc = 6;   { Sent to notify the application of preprocessor results }
-
-  { Return values for callback function }
-  iscrSuccess = 0;         { Return this for compiler to continue }
-  iscrRequestAbort = 1;    { Return this to abort compilation immediately.
-                             (When this value is returned, it is not necessary
-                             to set any of the "out" fields in the
-                             TCompilerCallbackData; the compiler will ignore
-                             them.) }
-
-  { Return values for ISDllCompileScript }
-  isceNoError = 0;         { Successful }
-  isceInvalidParam = 1;    { Bad parameters passed to function }
-  isceCompileFailure = 2;  { There was an error compiling or it was aborted
-                             by the application }
-
-type
-  { TCompilerCallbackData is a record passed to the callback function. The
-    fields which you may access vary depending on what Code was passed to the
-    callback function. }
-  TCompilerCallbackData = record
-    case Integer of
-      iscbReadScript: (
-        Reset: BOOL;          { [in] This field can be ignored in compiler
-                                versions 3.0.1 and later. (Previous versions
-                                of the compiler made multiple passes over the
-                                script, and set Reset to True when it needed
-                                to return to the beginning.) }
-        LineRead: PChar);     { [out] Application returns pointer to the next
-                                line it reads, or a NULL pointer if the end of
-                                file is reached. Application is responsible for
-                                allocating a buffer to hold the line; LineRead
-                                is initially NULL when the callback function
-                                is called. The pointer only needs to remain
-                                valid until the next time the callback function
-                                is called (i.e. the application may return the
-                                same pointer each time). }
-
-      iscbNotifyStatus: (
-        StatusMsg: PChar;     { [in] Contents of status message. }
-        Warning: BOOL);       { [in] Warning indicator (new in 6.0.0) }
-
-      iscbNotifyIdle: (
-        CompressProgress: Cardinal;     { [in] Amount compressed so far
-                                          (new in 4.1.6) }
-        CompressProgressMax: Cardinal;  { [in] Maximum value of CompressProgress
-                                          (new in 4.1.6) }
-        SecondsRemaining: Integer;      { [in] Estimated time remaining, or -1
-                                          if not known (new in 5.1.13) }
-        BytesCompressedPerSecond: Cardinal); { [in] Average bytes compressed
-                                               per second (new in 5.1.13) }
-
-      iscbNotifyPreproc: (
-        PreprocessedScript: PChar; { [in] Preprocessed script (new in 6.1.0) }
-        IncludedFilenames: PChar); { [in] Names of #included files. Each name is
-                                          a null-terminated string, and the final
-                                          name is followed by an additional null
-                                          character (new in 6.1.0) }
-
-      iscbNotifySuccess: (
-        OutputExeFilename: PChar;  { [in] The name of the resulting setup.exe,
-                                          or empty if output was disabled
-                                          (latter new in 5.5.5) }
-        DebugInfo: Pointer;        { [in] Debug info (new in 3.0.0.1) }
-        DebugInfoSize: Cardinal);  { [in] Size of debug info (new in 3.0.0.1) }
-
-      iscbNotifyError: (
-        ErrorMsg: PChar;      { [in] The error message, or NULL if compilation
-                                was aborted by the application. }
-        ErrorFilename: PChar; { [in] Filename in which the error occurred. This
-                                is NULL if the file is the main script. }
-        ErrorLine: Integer);  { [in] The line number the error occurred on.
-                                Zero if the error doesn't apply to any
-                                particular line. }
-  end;
-
-  TCompilerCallbackProc = function(Code: Integer;
-    var Data: TCompilerCallbackData; AppData: Longint): Integer; stdcall;
-
-  PCompileScriptParamsEx = ^TCompileScriptParamsEx;
-  TCompileScriptParamsEx = record
-    Size: Cardinal;       { [in] Set to SizeOf(TCompileScriptParamsEx). }
-    CompilerPath: PChar;  { [in] The "compiler:" directory. This is the
-                            directory which contains the *.e32 files. If this
-                            is set to NULL, the compiler will use the directory
-                            containing the compiler DLL/EXE. }
-    SourcePath: PChar;    { [in] The default source directory, and directory to
-                            look in for #include files. Normally, this is
-                            the directory containing the script file. This
-                            cannot be NULL. }
-    CallbackProc: TCompilerCallbackProc;
-                          { [in] The callback procedure which the compiler calls
-                            to read the script and for status notification. }
-    AppData: Longint;     { [in] Application-defined. AppData is passed to the
-                            callback function. }
-    Options: PChar;       { [in] Additional options. Each option is a
-                            null-terminated string, and the final option is
-                            followed by an additional null character.
-                            If you do not wish to specify any options, set this
-                            field to NULL or to point to a single null
-                            character.
-
-                            Currently supported options:
-
-                            Output=(0|no|false|1|yes|true)
-                              Enables or disables output.
-                            OutputBaseFilename=[filename]
-                              Overrides any OutputBaseFilename setting in the
-                              script; causes the compiler to use [filename]
-                              instead.
-                            OutputDir=[path]
-                              Overrides any output directory in the script;
-                              causes the compiler to use [path] instead.
-                            SignTool-[name]=[command]
-                              Configures a SignTool with name [name] and command
-                              [command].
-                            ISPP:[isppoption]
-                              Configures an ISPP option. }
-  end;
-
-  { The old TCompileScriptParams record. Use this in place of
-    TCompileScriptParamsEx if you need call ISCmplr.dll versions below
-    5.0.5. It's the same except it lacks an Options field. }
-  TCompileScriptParams = record
-    Size: Cardinal;       { [in] Set to SizeOf(TCompileScriptParams). }
-    CompilerPath: PChar;
-    SourcePath: PChar;
-    CallbackProc: TCompilerCallbackProc;
-    AppData: Longint;
-  end;
-
-  PCompilerVersionInfo = ^TCompilerVersionInfo;
-  TCompilerVersionInfo = record
-    Title: PAnsiChar;      { Name of compiler engine - 'Inno Setup' }
-    Version: PAnsiChar;    { Version number text }
-    BinVersion: Cardinal;  { Version number as an integer }
-  end;
+  Shared.CompilerInt.Struct;
 
 const
   ISCmplrDLL = 'ISCmplr.dll';
 
+var
+  ISCmplrLibrary: HMODULE;
+
 { The ISDllCompileScript function begins compilation of a script. See the above
   description of the TCompileScriptParams record. Return value is one of the
   isce* constants. }
-function ISDllCompileScript(const Params: TCompileScriptParamsEx): Integer;
-  stdcall; external ISCmplrDLL name 'ISDllCompileScriptW';
+  ISDllCompileScript: function(const Params: TCompileScriptParamsEx): Integer; stdcall;
 
 { The ISDllGetVersion returns a pointer to a TCompilerVersionInfo record which
   contains information about the compiler version. }
-function ISDllGetVersion: PCompilerVersionInfo; stdcall; external ISCmplrDLL;
+  ISDllGetVersion: function: PCompilerVersionInfo; stdcall;
+
+procedure InitISCmplrLibrary;
 
 implementation
 
+uses
+  Windows,
+  SysUtils,
+  PathFunc, TrustFunc;
+
+procedure InitISCmplrLibrary;
+begin
+  var FileName := AddBackslash(PathExtractPath(ParamStr(0))) + ISCmplrDLL;
+  ISCmplrLibrary := LoadTrustedLibrary(FileName, True);
+  if ISCmplrLibrary <> 0 then begin
+    ISDllCompileScript := GetProcAddress(ISCmplrLibrary, 'ISDllCompileScriptW');
+    ISDllGetVersion := GetProcAddress(ISCmplrLibrary, 'ISDllGetVersion');
+    if not Assigned(ISDllCompileScript) or not Assigned(ISDllGetVersion) then begin
+      FreeLibrary(ISCmplrLibrary);
+      ISCmplrLibrary := 0;
+      ISDllCompileScript := nil;
+      ISDllGetVersion := nil;
+    end;
+  end;
+end;
+
 end.

+ 2 - 2
Projects/Src/Shared.Struct.pas

@@ -17,8 +17,8 @@ uses
 
 const
   SetupTitle = 'Inno Setup';
-  SetupVersion = '6.4.2';
-  SetupBinVersion = (6 shl 24) + (4 shl 16) + (2 shl 8) + 0;
+  SetupVersion = '6.4.3-dev';
+  SetupBinVersion = (6 shl 24) + (4 shl 16) + (3 shl 8) + 0;
 
 type
   TSetupID = array[0..63] of AnsiChar;

+ 7 - 1
README.md

@@ -112,7 +112,7 @@ because they can function independently from Inno Setup.
 Overview
 --------
 
-Inno Setup consists of six projects:
+Inno Setup consists of seven projects:
 
 **Compil32** - This is the GUI front-end for the compiler, also known as
 the Compiler IDE. Compil32 does not do the actual compilation itself; it
@@ -137,6 +137,12 @@ performs all (un)installation-related tasks.
 Setup program into the user's TEMP directory and runs it from there. It also
 displays the "This will install..." and /HELP message boxes.
 
+**ISSigTool** - This is a command-line tool which can be used to sign and verify
+any file. Compil32, ISCC, and ISCmplr use these signatures to verify the
+authenticity of a number of DLL files before loading them. Note: this tool does
+not replace Microsoft's signtool.exe in any way and is in fact not related to
+Authenticode Code Signing at all.
+
 How do the projects link together?
 
 - Compil32, ISCmplr, ISPP, Setup, and SetupLdr share the unit Shared.Struct.pas.

+ 27 - 3
build-ce.bat

@@ -7,7 +7,8 @@ rem  For conditions of distribution and use, see LICENSE.TXT.
 rem
 rem  Batch file to prepare a release
 rem
-rem  Calls setup-sign.bat if it exists, else creates setup.exe without signing
+rem  Calls setup-sign.bat if it exists to create a signed build, otherwise creates setup.exe without signing
+rem  Signed builds also require a setup-presign.bat to exist which should sign all files passed to it
 rem
 rem  This batch files does the following things:
 rem  -Ask the user to compile Inno Setup including ISSigTool and ISHelpGen after clearing output first
@@ -18,7 +19,7 @@ rem  Once done the installer can be found in Output
 
 setlocal
 
-set VER=6.4.2
+set VER=6.4.3-dev
 
 echo Building Inno Setup %VER%...
 echo.
@@ -28,6 +29,20 @@ cd /d %~dp0
 if "%1"=="setup" goto setup
 if not "%1"=="" goto failed
 
+if not exist files\issigtool.exe (
+  echo Missing ISSigTool
+  echo Now open Projects\Projects.groupproj and build ISSigTool in Release mode
+
+  echo Waiting for file...
+  call :waitforfile files\issigtool.exe
+  echo Compiling ISSigTool done
+)
+
+call .\issig.bat embed
+if errorlevel 1 goto failed
+echo ISSigTool embed done
+
+echo.
 call :deletefile files\compil32.exe
 call :deletefile files\iscc.exe
 call :deletefile files\iscmplr.dll
@@ -37,7 +52,6 @@ call :deletefile files\setupldr.e32
 call :deletefile files\issigtool.exe
 call :deletefile ishelp\ishelpgen\ishelpgen.exe
 
-echo.
 echo Clearing compilation output done
 echo Now open Projects\Projects.groupproj and build all projects in Release mode
 
@@ -53,6 +67,16 @@ call :waitforfile ishelp\ishelpgen\ishelpgen.exe
 
 echo Found all, waiting 2 seconds more...
 timeout /t 2 /nobreak >nul
+echo Compiling Inno Setup done
+
+if exist .\setup-presign.bat (
+  call .\setup-presign.bat Files\ISCmplr.dll Files\ISPP.dll
+)
+
+call .\issig.bat sign
+if errorlevel 1 goto failed
+echo ISSigTool sign done
+pause
 
 cd ishelp
 if errorlevel 1 goto failed

+ 22 - 2
build.bat

@@ -7,7 +7,8 @@ rem  For conditions of distribution and use, see LICENSE.TXT.
 rem
 rem  Batch file to prepare a release
 rem
-rem  Calls setup-sign.bat if it exists, else creates setup.exe without signing
+rem  Calls setup-sign.bat if it exists to create a signed build, otherwise creates setup.exe without signing
+rem  Signed build also require a setup-presign.bat to exist which should sign all files passed to it
 rem
 rem  This batch files does the following things:
 rem  -Compile ISHelpGen
@@ -19,7 +20,7 @@ rem  Once done the installer can be found in Output
 
 setlocal
 
-set VER=6.4.2
+set VER=6.4.3-dev
 
 echo Building Inno Setup %VER%...
 echo.
@@ -47,9 +48,28 @@ if errorlevel 1 goto failed
 echo Compiling ISetup*.chm done
 pause
 
+if not exist files\issigtool.exe (
+  echo Missing ISSigTool
+  call .\compile.bat issigtool
+  if errorlevel 1 goto failed
+  echo Compiling ISSigTool done
+)
+
+call .\issig.bat embed
+if errorlevel 1 goto failed
+echo ISSigTool embed done
+
 call .\compile.bat
 if errorlevel 1 goto failed
 echo Compiling Inno Setup done
+
+if exist .\setup-presign.bat (
+  call .\setup-presign.bat Files\ISCmplr.dll Files\ISPP.dll
+) 
+
+call .\issig.bat sign
+if errorlevel 1 goto failed
+echo ISSigTool sign done
 pause
 
 :setup

+ 13 - 7
compile.bat

@@ -13,8 +13,8 @@ cd /d %~dp0
 
 if exist compilesettings.bat goto compilesettingsfound
 :compilesettingserror
-echo compilesettings.bat is missing or incomplete. It needs to be created
-echo with the following line, adjusted for your system:
+echo compilesettings.bat is missing or incomplete. It needs to contain
+echo the following line, adjusted for your system:
 echo.
 echo   set DELPHIXEROOT=C:\Program Files\Embarcadero\RAD Studio\20.0 [Path to Delphi 10.4 Sydney (or later)]
 goto failed2
@@ -35,6 +35,9 @@ set DELPHIXEDISABLEDWARNINGS=-W-SYMBOL_DEPRECATED -W-SYMBOL_PLATFORM -W-UNSAFE_C
 cd Projects
 if errorlevel 1 goto failed
 
+if "%1"=="issigtool" goto issigtool
+if not "%1"=="" goto failed
+
 echo - ISPP.dpr
 mkdir Dcu\ISPP.dpr 2>nul
 "%DELPHIXEROOT%\bin\dcc32.exe" --no-config -NSSystem;System.Win;Winapi -Q -B -H -W %DELPHIXEDISABLEDWARNINGS% %1 -U"%DELPHIXEROOT%\lib\win32\release" -E..\Files -NUDcu\ISPP.dpr ISPP.dpr
@@ -65,11 +68,6 @@ mkdir Dcu\Setup.dpr 2>nul
 "%DELPHIXEROOT%\bin\dcc32.exe" --no-config -NSSystem;System.Win;Winapi;Vcl -Q -B -W %DELPHIXEDISABLEDWARNINGS% %1 -U"%DELPHIXEROOT%\lib\win32\release;..\Components\UniPs\Source" -E..\Files -NUDcu\Setup.dpr -DSETUPPROJ;PS_MINIVCL;PS_NOGRAPHCONST;PS_PANSICHAR;PS_NOINTERFACEGUIDBRACKETS Setup.dpr
 if errorlevel 1 goto failed
 
-echo - ISSigTool.dpr
-mkdir Dcu\ISSigTool.dpr 2>nul
-"%DELPHIXEROOT%\bin\dcc32.exe" --no-config -NSSystem;System.Win;Winapi -Q -B -H -W %DELPHIXEDISABLEDWARNINGS% %1 -U"%DELPHIXEROOT%\lib\win32\release" -E..\Files -NUDcu\ISSigTool.dpr ISSigTool.dpr
-if errorlevel 1 goto failed
-
 echo - Renaming E32 files
 cd ..\Files
 if errorlevel 1 goto failed
@@ -77,6 +75,14 @@ move SetupLdr.exe SetupLdr.e32
 if errorlevel 1 goto failed
 move Setup.exe Setup.e32
 if errorlevel 1 goto failed
+cd ..\Projects
+if errorlevel 1 goto failed
+
+:issigtool
+echo - ISSigTool.dpr
+mkdir Dcu\ISSigTool.dpr 2>nul
+"%DELPHIXEROOT%\bin\dcc32.exe" --no-config -NSSystem;System.Win;Winapi -Q -B -H -W %DELPHIXEDISABLEDWARNINGS% %1 -U"%DELPHIXEROOT%\lib\win32\release" -E..\Files -NUDcu\ISSigTool.dpr ISSigTool.dpr
+if errorlevel 1 goto failed
 
 cd ..
 if errorlevel 1 goto failed

+ 77 - 0
issig.bat

@@ -0,0 +1,77 @@
+@echo off
+
+rem  Inno Setup
+rem  Copyright (C) 1997-2025 Jordan Russell
+rem  Portions by Martijn Laan
+rem  For conditions of distribution and use, see LICENSE.TXT.
+rem
+rem  Batch file to embed the public key in TrustFunc.AllowedPublicKeys.inc (before compilation) or to create ISCmplr.dll.issig and ISPP.dll.issig (after compilation)
+rem  Also generates a new private key if needed
+
+setlocal
+
+cd /d %~dp0
+
+if exist compilesettings.bat goto compilesettingsfound
+:compilesettingserror
+echo compilesettings.bat is missing or incomplete. It needs to contain
+echo the following line, adjusted for your system:
+echo.
+echo   set ISSIGTOOL_KEY_FILE=x:\path\MyKey.isprivatekey
+goto failed2
+
+:compilesettingsfound
+set ISSIGTOOL_KEY_FILE=
+call .\compilesettings.bat
+if "%ISSIGTOOL_KEY_FILE%"=="" goto compilesettingserror
+
+rem -------------------------------------------------------------------------
+
+cd Files
+if errorlevel 1 goto failed
+
+if not exist "%ISSIGTOOL_KEY_FILE%" (
+  echo Missing key file
+  ISSigTool.exe generate-private-key
+  if errorlevel 1 goto failed
+  if not exist "%ISSIGTOOL_KEY_FILE%" goto failed
+  echo Generating key file done - do not share with others!
+)
+
+if "%1"=="embed" goto embed
+if "%1"=="sign" goto sign
+if not "%1"=="" goto failed
+
+:embed
+set targetfile=..\Components\TrustFunc.AllowedPublicKeys.inc
+if not exist "%targetfile%" goto failed
+set publickeyfile=_temp.ispublickey
+ISSigTool.exe export-public-key "%publickeyfile%"
+if errorlevel 1 goto failed
+if not exist "%publickeyfile%" goto failed
+powershell.exe -NoProfile -Command "$filePath = '%targetfile%'; $replacementFilePath = '%publickeyfile%'; $startMarker = \"AllowedPublicKey2Text := '''\"; $endMarker = \"''';//end\"; try { $content = Get-Content -Raw -Path $filePath; $replacementText = Get-Content -Raw -Path $replacementFilePath; [string] $pattern = '(?s)' + [regex]::Escape($startMarker) + '.*?' + [regex]::Escape($endMarker); if ($content -match $pattern) { $replacement = $startMarker + \"`r`n\" + $replacementText + \"`r`n\" + $endMarker; $newContent = $content -replace $pattern, $replacement; $utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($false); [System.IO.File]::WriteAllText($filePath, $newContent, $utf8NoBomEncoding); Write-Host 'Embedded key.'; } else { Write-Host 'Markers not found.'; exit 1; } } catch { Write-Error ('Error: ' + $_.Exception.Message); exit 1; }"
+if errorlevel 1 goto failed
+del "%publickeyfile%"
+if errorlevel 1 goto failed
+cd ..
+if errorlevel 1 goto failed
+
+echo Success!
+goto exit
+
+:sign
+ISSigTool.exe sign ISCmplr.dll ISPP.dll
+if errorlevel 1 goto failed
+cd ..
+if errorlevel 1 goto failed
+
+echo Success!
+goto exit
+
+:failed
+echo *** FAILED ***
+cd ..
+:failed2
+exit /b 1
+
+:exit

+ 18 - 11
setup.iss

@@ -13,7 +13,7 @@
 [Setup]
 AppName=Inno Setup
 AppId={code:GetAppId|Inno Setup 6}
-AppVersion=6.4.2
+AppVersion=6.4.3-dev
 AppPublisher=jrsoftware.org
 AppPublisherURL=https://www.innosetup.com/
 AppSupportURL=https://www.innosetup.com/
@@ -117,7 +117,8 @@ Source: "license.txt"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\ISetup.chm"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\ISetup-dark.chm"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\Compil32.exe"; DestDir: "{app}"; Flags: ignoreversion signonce touch
-Source: "files\isscint.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
+Source: "files\isscint.dll"; DestDir: "{app}"; Flags: ignoreversion signcheck touch
+Source: "files\isscint.dll.issig"; DestDir: "{app}"; Flags: ignoreversion touch
 #ifndef isccexe
   #define isccexe "ISCC.exe"
 #endif
@@ -125,7 +126,8 @@ Source: "files\{#isccexe}"; DestName: "ISCC.exe"; DestDir: "{app}"; Flags: ignor
 #ifndef iscmplrdll
   #define iscmplrdll "ISCmplr.dll"
 #endif
-Source: "files\{#iscmplrdll}"; DestName: "ISCmplr.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
+Source: "files\{#iscmplrdll}"; DestName: "ISCmplr.dll"; DestDir: "{app}"; Flags: ignoreversion signcheck touch
+Source: "files\ISCmplr.dll.issig"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\Setup.e32"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\SetupLdr.e32"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\Default.isl"; DestDir: "{app}"; Flags: ignoreversion touch
@@ -135,16 +137,26 @@ Source: "files\WizClassicImage.bmp"; DestDir: "{app}"; Flags: ignoreversion touc
 Source: "files\WizClassicImage-IS.bmp"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\WizClassicSmallImage.bmp"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\WizClassicSmallImage-IS.bmp"; DestDir: "{app}"; Flags: ignoreversion touch
-Source: "files\iszlib.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
+Source: "files\iszlib.dll"; DestDir: "{app}"; Flags: ignoreversion signcheck touch
+Source: "files\iszlib.dll.issig"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\isunzlib.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
-Source: "files\isbzip.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
+Source: "files\isbzip.dll"; DestDir: "{app}"; Flags: ignoreversion signcheck touch
+Source: "files\isbzip.dll.issig"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\isbunzip.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
 #ifndef islzmadll
   #define islzmadll "islzma.dll"
 #endif
-Source: "files\{#islzmadll}"; DestName: "islzma.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
+Source: "files\{#islzmadll}"; DestName: "islzma.dll"; DestDir: "{app}"; Flags: ignoreversion signcheck touch
+Source: "files\islzma.dll.issig"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "files\islzma32.exe"; DestDir: "{app}"; Flags: ignoreversion signonce touch
 Source: "files\islzma64.exe"; DestDir: "{app}"; Flags: ignoreversion signonce touch
+#ifndef isppdll
+  #define isppdll "ispp.dll"
+#endif
+Source: "files\{#isppdll}"; DestName: "ISPP.dll"; DestDir: "{app}"; Flags: ignoreversion signcheck touch
+Source: "files\ISPP.dll.issig"; DestDir: "{app}"; Flags: ignoreversion touch
+Source: "files\ISPPBuiltins.iss"; DestDir: "{app}"; Flags: ignoreversion touch
+Source: "files\ISSigTool.exe"; DestDir: "{app}"; Flags: ignoreversion signonce touch
 Source: "whatsnew.htm"; DestDir: "{app}"; Flags: ignoreversion touch
 Source: "Examples\64Bit.iss"; DestDir: "{app}\Examples"; Flags: ignoreversion touch
 Source: "Examples\64BitTwoArch.iss"; DestDir: "{app}\Examples"; Flags: ignoreversion touch
@@ -186,11 +198,6 @@ Source: "Examples\MyDll\C#\MyDll.sln"; DestDir: "{app}\Examples\MyDll\C#"; Flags
 Source: "Examples\MyDll\C#\packages.config"; DestDir: "{app}\Examples\MyDll\C#"; Flags: ignoreversion touch
 Source: "Examples\MyDll\C#\Properties\AssemblyInfo.cs"; DestDir: "{app}\Examples\MyDll\C#\Properties"; Flags: ignoreversion touch
 Source: "Examples\MyDll\Delphi\MyDll.dpr"; DestDir: "{app}\Examples\MyDll\Delphi"; Flags: ignoreversion touch
-#ifndef isppdll
-  #define isppdll "ispp.dll"
-#endif
-Source: "files\{#isppdll}"; DestName: "ISPP.dll"; DestDir: "{app}"; Flags: ignoreversion signonce touch
-Source: "files\ISPPBuiltins.iss"; DestDir: "{app}"; Flags: ignoreversion touch
 
 [INI]
 Filename: "{app}\isfaq.url"; Section: "InternetShortcut"; Key: "URL"; String: "https://jrsoftware.org/isfaq.php" 

+ 1 - 0
whatsnew.htm

@@ -32,6 +32,7 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
 <p><a name="6.4.3"></a><span class="ver">6.4.3-dev </span><span class="date">(?)</span></p>
 <ul>
   <li>Compiler IDE change: The editor now restores selections on undo and redo.</li>
+  <li>Inno Setup now includes a new command-line tool, ISSigTool.exe. This tool is designed to sign files using cryptographic signatures. Compil32, ISCC, and ISCmplr use these signatures to verify a number of DLL files before loading them.<br />Note: ISSigTool.exe does not replace Microsoft's signtool.exe in any way and is in fact not related to Authenticode Code Signing at all.</li>
 </ul>
 
 <p><a name="6.4.2"></a><span class="ver">6.4.2 </span><span class="date">(2025-03-12)</span></p>