Procházet zdrojové kódy

Cleanup: there was a Shared.ResUpdateFunc claiming it was used by Setup while it wasn't. Move its code into Compiler.ExeUpdateFunc and remove it.

Martijn Laan před 2 týdny
rodič
revize
5c9f6e828f

+ 0 - 1
Projects/ISCmplr.dpr

@@ -26,7 +26,6 @@ uses
   Compiler.ScriptFunc in 'Src\Compiler.ScriptFunc.pas',
   Compiler.ScriptCompiler in 'Src\Compiler.ScriptCompiler.pas',
   Compiler.ScriptClasses in 'Src\Compiler.ScriptClasses.pas',
-  Shared.ResUpdateFunc in 'Src\Shared.ResUpdateFunc.pas',
   Compiler.ExeUpdateFunc in 'Src\Compiler.ExeUpdateFunc.pas',
   Compression.Base in 'Src\Compression.Base.pas',
   Compression.Zlib in 'Src\Compression.Zlib.pas',

+ 0 - 1
Projects/ISCmplr.dproj

@@ -94,7 +94,6 @@
         <DCCReference Include="Src\Compiler.ScriptFunc.pas"/>
         <DCCReference Include="Src\Compiler.ScriptCompiler.pas"/>
         <DCCReference Include="Src\Compiler.ScriptClasses.pas"/>
-        <DCCReference Include="Src\Shared.ResUpdateFunc.pas"/>
         <DCCReference Include="Src\Compiler.ExeUpdateFunc.pas"/>
         <DCCReference Include="Src\Compression.Base.pas"/>
         <DCCReference Include="Src\Compression.Zlib.pas"/>

+ 0 - 1
Projects/Setup.dpr

@@ -71,7 +71,6 @@ uses
   Setup.Helper in 'Src\Setup.Helper.pas',
   Shared.VerInfoFunc in 'Src\Shared.VerInfoFunc.pas',
   Setup.RegDLL in 'Src\Setup.RegDLL.pas',
-  Shared.ResUpdateFunc in 'Src\Shared.ResUpdateFunc.pas',
   Setup.SpawnCommon in 'Src\Setup.SpawnCommon.pas',
   Setup.SpawnServer in 'Src\Setup.SpawnServer.pas',
   Setup.SpawnClient in 'Src\Setup.SpawnClient.pas',

+ 0 - 1
Projects/Setup.dproj

@@ -144,7 +144,6 @@
         <DCCReference Include="Src\Setup.Helper.pas"/>
         <DCCReference Include="Src\Shared.VerInfoFunc.pas"/>
         <DCCReference Include="Src\Setup.RegDLL.pas"/>
-        <DCCReference Include="Src\Shared.ResUpdateFunc.pas"/>
         <DCCReference Include="Src\Setup.SpawnCommon.pas"/>
         <DCCReference Include="Src\Setup.SpawnServer.pas"/>
         <DCCReference Include="Src\Setup.SpawnClient.pas"/>

+ 362 - 1
Projects/Src/Compiler.ExeUpdateFunc.pas

@@ -14,6 +14,14 @@ interface
 uses
   Windows, SysUtils, Shared.FileClass, Shared.VerInfoFunc;
 
+function ReadSignatureAndChecksumFields(const F: TCustomFile;
+  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
+function ReadSignatureAndChecksumFields64(const F: TCustomFile;
+  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
+function SeekToResourceData(const F: TCustomFile; const ResType, ResId: Cardinal): Cardinal;
+function UpdateSignatureAndChecksumFields(const F: TCustomFile;
+  const ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
+  
 procedure UpdateSetupPEHeaderFields(const F: TCustomFile;
   const IsTSAware, IsDEPCompatible, IsASLRCompatible: Boolean);
 procedure UpdateIcons(const FileName, IcoFileName: String; const DeleteUninstallIcon: Boolean);
@@ -27,7 +35,360 @@ procedure PreventCOMCTL32Sideloading(const F: TCustomFile);
 implementation
 
 uses
-  Shared.ResUpdateFunc, Math;
+  Math;
+
+const
+  IMAGE_NT_SIGNATURE = $00004550;
+  IMAGE_NT_OPTIONAL_HDR32_MAGIC = $10b;
+  IMAGE_NT_OPTIONAL_HDR64_MAGIC = $20b;
+  IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
+  IMAGE_SIZEOF_SHORT_NAME = 8;
+  IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
+  IMAGE_DIRECTORY_ENTRY_SECURITY = 4;
+
+type
+  PImageFileHeader = ^TImageFileHeader;
+  TImageFileHeader = packed record
+    Machine: Word;
+    NumberOfSections: Word;
+    TimeDateStamp: DWORD;
+    PointerToSymbolTable: DWORD;
+    NumberOfSymbols: DWORD;
+    SizeOfOptionalHeader: Word;
+    Characteristics: Word;
+  end;
+  PImageDataDirectory = ^TImageDataDirectory;
+  TImageDataDirectory = record
+    VirtualAddress: DWORD;
+    Size: DWORD;
+  end;
+  PImageOptionalHeader = ^TImageOptionalHeader;
+  TImageOptionalHeader = packed record
+    { Standard fields. }
+    Magic: Word;
+    MajorLinkerVersion: Byte;
+    MinorLinkerVersion: Byte;
+    SizeOfCode: DWORD;
+    SizeOfInitializedData: DWORD;
+    SizeOfUninitializedData: DWORD;
+    AddressOfEntryPoint: DWORD;
+    BaseOfCode: DWORD;
+    BaseOfData: DWORD;
+    { NT additional fields. }
+    ImageBase: DWORD;
+    SectionAlignment: DWORD;
+    FileAlignment: DWORD;
+    MajorOperatingSystemVersion: Word;
+    MinorOperatingSystemVersion: Word;
+    MajorImageVersion: Word;
+    MinorImageVersion: Word;
+    MajorSubsystemVersion: Word;
+    MinorSubsystemVersion: Word;
+    Win32VersionValue: DWORD;
+    SizeOfImage: DWORD;
+    SizeOfHeaders: DWORD;
+    CheckSum: DWORD;
+    Subsystem: Word;
+    DllCharacteristics: Word;
+    SizeOfStackReserve: DWORD;
+    SizeOfStackCommit: DWORD;
+    SizeOfHeapReserve: DWORD;
+    SizeOfHeapCommit: DWORD;
+    LoaderFlags: DWORD;
+    NumberOfRvaAndSizes: DWORD;
+    DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
+  end;
+  PImageOptionalHeader64 = ^TImageOptionalHeader64;
+  TImageOptionalHeader64 = packed record
+    { Standard fields. }
+    Magic: Word;
+    MajorLinkerVersion: Byte;
+    MinorLinkerVersion: Byte;
+    SizeOfCode: DWORD;
+    SizeOfInitializedData: DWORD;
+    SizeOfUninitializedData: DWORD;
+    AddressOfEntryPoint: DWORD;
+    BaseOfCode: DWORD;
+    { NT additional fields. }
+    ImageBase: Int64;
+    SectionAlignment: DWORD;
+    FileAlignment: DWORD;
+    MajorOperatingSystemVersion: Word;
+    MinorOperatingSystemVersion: Word;
+    MajorImageVersion: Word;
+    MinorImageVersion: Word;
+    MajorSubsystemVersion: Word;
+    MinorSubsystemVersion: Word;
+    Win32VersionValue: DWORD;
+    SizeOfImage: DWORD;
+    SizeOfHeaders: DWORD;
+    CheckSum: DWORD;
+    Subsystem: Word;
+    DllCharacteristics: Word;
+    SizeOfStackReserve: Int64;
+    SizeOfStackCommit: Int64;
+    SizeOfHeapReserve: Int64;
+    SizeOfHeapCommit: Int64;
+    LoaderFlags: DWORD;
+    NumberOfRvaAndSizes: DWORD;
+    DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
+  end;
+  TISHMisc = packed record
+    case Integer of
+      0: (PhysicalAddress: DWORD);
+      1: (VirtualSize: DWORD);
+  end;
+  PImageSectionHeader = ^TImageSectionHeader;
+  TImageSectionHeader = packed record
+    Name: packed array[0..IMAGE_SIZEOF_SHORT_NAME-1] of Byte;
+    Misc: TISHMisc;
+    VirtualAddress: DWORD;
+    SizeOfRawData: DWORD;
+    PointerToRawData: DWORD;
+    PointerToRelocations: DWORD;
+    PointerToLinenumbers: DWORD;
+    NumberOfRelocations: Word;
+    NumberOfLinenumbers: Word;
+    Characteristics: DWORD;
+  end;
+  TImageResourceDirectory = packed record
+    Characteristics: DWORD;
+    TimeDateStamp: DWORD;
+    MajorVersion: Word;
+    MinorVersion: Word;
+    NumberOfNamedEntries: Word;
+    NumberOfIdEntries: Word;
+  end;
+  TImageResourceDirectoryEntry = packed record
+    Id: DWORD;
+    Offset: DWORD;
+  end;
+  TImageResourceDataEntry = packed record
+    OffsetToData: DWORD;
+    Size: DWORD;
+    CodePage: DWORD;
+    Reserved: DWORD;
+  end;
+
+procedure Error(const Msg: String);
+begin
+  raise Exception.Create('Resource update error: ' + Msg);
+end;
+
+function SeekToPEHeader(const F: TCustomFile): Boolean;
+var
+  DosHeader: packed record
+    Sig: array[0..1] of AnsiChar;
+    Other: array[0..57] of Byte;
+    PEHeaderOffset: LongWord;
+  end;
+  Sig: DWORD;
+begin
+  Result := False;
+  F.Seek(0);
+  if F.Read(DosHeader, SizeOf(DosHeader)) = SizeOf(DosHeader) then begin
+    if (DosHeader.Sig[0] = 'M') and (DosHeader.Sig[1] = 'Z') and
+       (DosHeader.PEHeaderOffset <> 0) then begin
+      F.Seek(DosHeader.PEHeaderOffset);
+      if F.Read(Sig, SizeOf(Sig)) = SizeOf(Sig) then
+        if Sig = IMAGE_NT_SIGNATURE then
+          Result := True;
+    end;
+  end;
+end;
+
+function SeekToAndReadPEOptionalHeader(const F: TCustomFile;
+  var OptHeader: TImageOptionalHeader; var OptHeaderOffset: Int64): Boolean;
+var
+  Header: TImageFileHeader;
+begin
+  Result := False;
+  if SeekToPEHeader(F) then begin
+    if (F.Read(Header, SizeOf(Header)) = SizeOf(Header)) and
+       (Header.SizeOfOptionalHeader = SizeOf(OptHeader)) then begin
+      OptHeaderOffset := F.Position;
+      if F.Read(OptHeader, SizeOf(OptHeader)) = SizeOf(OptHeader) then
+        if OptHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC then
+          Result := True;
+    end;
+  end;
+end;
+
+function SeekToAndReadPEOptionalHeader64(const F: TCustomFile;
+  var OptHeader: TImageOptionalHeader64; var OptHeaderOffset: Int64): Boolean;
+var
+  Header: TImageFileHeader;
+begin
+  Result := False;
+  if SeekToPEHeader(F) then begin
+    if (F.Read(Header, SizeOf(Header)) = SizeOf(Header)) and
+       (Header.SizeOfOptionalHeader = SizeOf(OptHeader)) then begin
+      OptHeaderOffset := F.Position;
+      if F.Read(OptHeader, SizeOf(OptHeader)) = SizeOf(OptHeader) then
+        if OptHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC then
+          Result := True;
+    end;
+  end;
+end;
+
+procedure FindResourceSection(const F: TCustomFile;
+  var SectionVirtualAddr, SectionPhysOffset, SectionPhysSize: Cardinal);
+var
+  EXESig: Word;
+  PEHeaderOffset, PESig: Cardinal;
+  PEHeader: TImageFileHeader;
+  PEOptHeader: TImageOptionalHeader;
+  PESectionHeader: TImageSectionHeader;
+  I: Integer;
+begin
+  { Read DOS header }
+  F.Seek(0);
+  F.ReadBuffer(EXESig, SizeOf(EXESig));
+  if EXESig <> $5A4D {'MZ'} then
+    Error('File isn''t an EXE file (1)');
+  F.Seek($3C);
+  F.ReadBuffer(PEHeaderOffset, SizeOf(PEHeaderOffset));
+  if PEHeaderOffset = 0 then
+    Error('File isn''t a PE file (1)');
+
+  { Read PE header & optional header }
+  F.Seek(PEHeaderOffset);
+  F.ReadBuffer(PESig, SizeOf(PESig));
+  if PESig <> $00004550 {'PE'#0#0} then
+    Error('File isn''t a PE file (2)');
+  F.ReadBuffer(PEHeader, SizeOf(PEHeader));
+  if PEHeader.SizeOfOptionalHeader <> SizeOf(PEOptHeader) then
+    Error('File isn''t a PE file (3)');
+  F.ReadBuffer(PEOptHeader, SizeOf(PEOptHeader));
+  if PEOptHeader.Magic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC then
+    Error('File isn''t a PE file (4)');
+
+  { Scan section headers for resource section }
+  if (PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = 0) or
+     (PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = 0) then
+    Error('No resources (1)');
+  SectionVirtualAddr := PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+  SectionPhysOffset := 0;
+  for I := 0 to PEHeader.NumberOfSections-1 do begin
+    F.ReadBuffer(PESectionHeader, SizeOf(PESectionHeader));
+    if (PESectionHeader.VirtualAddress = SectionVirtualAddr) and
+       (PESectionHeader.SizeOfRawData <> 0) then begin
+      SectionPhysOffset := PESectionHeader.PointerToRawData;
+      SectionPhysSize := PESectionHeader.SizeOfRawData;
+      Break;
+    end;
+  end;
+  if SectionPhysOffset = 0 then
+    Error('No resources (2)');
+end;
+
+function FindResOffset(const F: TCustomFile; const AnyId: Boolean;
+  const Id: Cardinal; const FindSubdir: Boolean; var Offset: Cardinal): Boolean;
+var
+  Dir: TImageResourceDirectory;
+  Entry: TImageResourceDirectoryEntry;
+  I: Integer;
+begin
+  F.ReadBuffer(Dir, SizeOf(Dir));
+  { Skip over named entries }
+  for I := 0 to Dir.NumberOfNamedEntries-1 do
+    F.ReadBuffer(Entry, SizeOf(Entry));
+  { Now process ID entries }
+  Result := False;
+  for I := 0 to Dir.NumberOfIdEntries-1 do begin
+    F.ReadBuffer(Entry, SizeOf(Entry));
+    if (AnyId or (Entry.Id = Id)) and
+       ((Entry.Offset and $80000000 <> 0) = FindSubdir) then begin
+      Offset := Entry.Offset and $7FFFFFFF;
+      Result := True;
+      Break;
+    end;
+  end;
+end;
+
+function SeekToResourceData(const F: TCustomFile; const ResType, ResId: Cardinal): Cardinal;
+{ Seeks to the specified resource's data, and returns its size. Raises an
+  exception if the resource cannot be found. }
+var
+  SectionVirtualAddr, SectionPhysOffset, SectionPhysSize, Ofs: Cardinal;
+  DataEntry: TImageResourceDataEntry;
+begin
+  FindResourceSection(F, SectionVirtualAddr, SectionPhysOffset, SectionPhysSize);
+
+  { Scan the resource directory }
+  F.Seek(SectionPhysOffset);
+  if not FindResOffset(F, False, ResType, True, Ofs) then
+    Error('Can''t find resource (1)');
+  F.Seek(SectionPhysOffset + Ofs);
+  if not FindResOffset(F, False, ResId, True, Ofs) then
+    Error('Can''t find resource (2)');
+  F.Seek(SectionPhysOffset + Ofs);
+  if not FindResOffset(F, True, 0, False, Ofs) then
+    Error('Can''t find resource (3).');
+  F.Seek(SectionPhysOffset + Ofs);
+  F.ReadBuffer(DataEntry, SizeOf(DataEntry));
+
+  { Sanity check: DataEntry.OffsetToData is an RVA. It's technically possible
+    for the RVA to point to a different section, but we don't support that. }
+  if Cardinal(DataEntry.OffsetToData) < SectionVirtualAddr then
+    Error('Invalid resource (1)');
+  if Cardinal(DataEntry.OffsetToData - SectionVirtualAddr + DataEntry.Size) > SectionPhysSize then
+    Error('Invalid resource (2)');
+
+  { Seek to the resource }
+  F.Seek(SectionPhysOffset + (DataEntry.OffsetToData - SectionVirtualAddr));
+  Result := DataEntry.Size;
+end;
+
+function ReadSignatureAndChecksumFields(const F: TCustomFile;
+  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
+{ Reads the signature and checksum fields in the specified file's header.
+  If the file is not a valid PE32 executable, False is returned. }
+var
+  OptHeader: TImageOptionalHeader;
+  OptHeaderOffset: Int64;
+begin
+  Result := SeekToAndReadPEOptionalHeader(F, OptHeader, OptHeaderOffset);
+  if Result then begin
+    ASignatureAddress := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
+    ASignatureSize := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+    AChecksum := OptHeader.CheckSum;
+  end;
+end;
+
+function ReadSignatureAndChecksumFields64(const F: TCustomFile;
+  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
+{ Reads the signature and checksum fields in the specified file's header.
+  If the file is not a valid PE32+ executable, False is returned. }
+var
+  OptHeader: TImageOptionalHeader64;
+  OptHeaderOffset: Int64;
+begin
+  Result := SeekToAndReadPEOptionalHeader64(F, OptHeader, OptHeaderOffset);
+  if Result then begin
+    ASignatureAddress := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
+    ASignatureSize := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+    AChecksum := OptHeader.CheckSum;
+  end;
+end;
+
+function UpdateSignatureAndChecksumFields(const F: TCustomFile;
+  const ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
+{ Sets the signature and checksum fields in the specified file's header.
+  If the file is not a valid PE32 executable, False is returned. }
+var
+  OptHeader: TImageOptionalHeader;
+  OptHeaderOffset: Int64;
+begin
+  Result := SeekToAndReadPEOptionalHeader(F, OptHeader, OptHeaderOffset);
+  if Result then begin
+    OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress := ASignatureAddress;
+    OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size := ASignatureSize;
+    OptHeader.CheckSum := AChecksum;
+    F.Seek(OptHeaderOffset);
+    F.WriteBuffer(OptHeader, SizeOf(OptHeader));
+  end;
+end;
 
 procedure UpdateSetupPEHeaderFields(const F: TCustomFile;
   const IsTSAware, IsDEPCompatible, IsASLRCompatible: Boolean);

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

@@ -304,7 +304,7 @@ uses
   Commctrl, TypInfo, AnsiStrings, Math, WideStrUtils,
   PathFunc, TrustFunc, ISSigFunc, ECDSA, Shared.CommonFunc, Compiler.Messages, Shared.SetupEntFunc,
   Shared.FileClass, Shared.EncryptionFunc, Compression.Base, Compression.Zlib, Compression.bzlib,
-  Shared.LangOptionsSectionDirectives, Shared.ResUpdateFunc, Compiler.ExeUpdateFunc,
+  Shared.LangOptionsSectionDirectives, Compiler.ExeUpdateFunc,
 {$IFDEF STATICPREPROC}
   ISPP.Preprocess,
 {$ENDIF}

+ 0 - 410
Projects/Src/Shared.ResUpdateFunc.pas

@@ -1,410 +0,0 @@
-unit Shared.ResUpdateFunc;
-
-{
-  Inno Setup
-  Copyright (C) 1997-2025 Jordan Russell
-  Portions by Martijn Laan
-  For conditions of distribution and use, see LICENSE.TXT.
-
-  Resource update functions used by both Setup and the compiler
-}
-
-interface
-
-uses
-  Windows, SysUtils, Shared.FileClass;
-
-function ReadSignatureAndChecksumFields(const F: TCustomFile;
-  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
-function ReadSignatureAndChecksumFields64(const F: TCustomFile;
-  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
-function SeekToResourceData(const F: TCustomFile; const ResType, ResId: Cardinal): Cardinal;
-function UpdateSignatureAndChecksumFields(const F: TCustomFile;
-  const ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
-procedure UpdateManifestRequestedExecutionLevel(const F: TCustomFile;
-  const RequireAdministrator: Boolean);
-
-implementation
-
-const
-  IMAGE_NT_SIGNATURE = $00004550;
-  IMAGE_NT_OPTIONAL_HDR32_MAGIC = $10b;
-  IMAGE_NT_OPTIONAL_HDR64_MAGIC = $20b;
-  IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
-  IMAGE_SIZEOF_SHORT_NAME = 8;
-  IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
-  IMAGE_DIRECTORY_ENTRY_SECURITY = 4;
-
-type
-  PImageFileHeader = ^TImageFileHeader;
-  TImageFileHeader = packed record
-    Machine: Word;
-    NumberOfSections: Word;
-    TimeDateStamp: DWORD;
-    PointerToSymbolTable: DWORD;
-    NumberOfSymbols: DWORD;
-    SizeOfOptionalHeader: Word;
-    Characteristics: Word;
-  end;
-  PImageDataDirectory = ^TImageDataDirectory;
-  TImageDataDirectory = record
-    VirtualAddress: DWORD;
-    Size: DWORD;
-  end;
-  PImageOptionalHeader = ^TImageOptionalHeader;
-  TImageOptionalHeader = packed record
-    { Standard fields. }
-    Magic: Word;
-    MajorLinkerVersion: Byte;
-    MinorLinkerVersion: Byte;
-    SizeOfCode: DWORD;
-    SizeOfInitializedData: DWORD;
-    SizeOfUninitializedData: DWORD;
-    AddressOfEntryPoint: DWORD;
-    BaseOfCode: DWORD;
-    BaseOfData: DWORD;
-    { NT additional fields. }
-    ImageBase: DWORD;
-    SectionAlignment: DWORD;
-    FileAlignment: DWORD;
-    MajorOperatingSystemVersion: Word;
-    MinorOperatingSystemVersion: Word;
-    MajorImageVersion: Word;
-    MinorImageVersion: Word;
-    MajorSubsystemVersion: Word;
-    MinorSubsystemVersion: Word;
-    Win32VersionValue: DWORD;
-    SizeOfImage: DWORD;
-    SizeOfHeaders: DWORD;
-    CheckSum: DWORD;
-    Subsystem: Word;
-    DllCharacteristics: Word;
-    SizeOfStackReserve: DWORD;
-    SizeOfStackCommit: DWORD;
-    SizeOfHeapReserve: DWORD;
-    SizeOfHeapCommit: DWORD;
-    LoaderFlags: DWORD;
-    NumberOfRvaAndSizes: DWORD;
-    DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
-  end;
-  PImageOptionalHeader64 = ^TImageOptionalHeader64;
-  TImageOptionalHeader64 = packed record
-    { Standard fields. }
-    Magic: Word;
-    MajorLinkerVersion: Byte;
-    MinorLinkerVersion: Byte;
-    SizeOfCode: DWORD;
-    SizeOfInitializedData: DWORD;
-    SizeOfUninitializedData: DWORD;
-    AddressOfEntryPoint: DWORD;
-    BaseOfCode: DWORD;
-    { NT additional fields. }
-    ImageBase: Int64;
-    SectionAlignment: DWORD;
-    FileAlignment: DWORD;
-    MajorOperatingSystemVersion: Word;
-    MinorOperatingSystemVersion: Word;
-    MajorImageVersion: Word;
-    MinorImageVersion: Word;
-    MajorSubsystemVersion: Word;
-    MinorSubsystemVersion: Word;
-    Win32VersionValue: DWORD;
-    SizeOfImage: DWORD;
-    SizeOfHeaders: DWORD;
-    CheckSum: DWORD;
-    Subsystem: Word;
-    DllCharacteristics: Word;
-    SizeOfStackReserve: Int64;
-    SizeOfStackCommit: Int64;
-    SizeOfHeapReserve: Int64;
-    SizeOfHeapCommit: Int64;
-    LoaderFlags: DWORD;
-    NumberOfRvaAndSizes: DWORD;
-    DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
-  end;
-  TISHMisc = packed record
-    case Integer of
-      0: (PhysicalAddress: DWORD);
-      1: (VirtualSize: DWORD);
-  end;
-  PImageSectionHeader = ^TImageSectionHeader;
-  TImageSectionHeader = packed record
-    Name: packed array[0..IMAGE_SIZEOF_SHORT_NAME-1] of Byte;
-    Misc: TISHMisc;
-    VirtualAddress: DWORD;
-    SizeOfRawData: DWORD;
-    PointerToRawData: DWORD;
-    PointerToRelocations: DWORD;
-    PointerToLinenumbers: DWORD;
-    NumberOfRelocations: Word;
-    NumberOfLinenumbers: Word;
-    Characteristics: DWORD;
-  end;
-  TImageResourceDirectory = packed record
-    Characteristics: DWORD;
-    TimeDateStamp: DWORD;
-    MajorVersion: Word;
-    MinorVersion: Word;
-    NumberOfNamedEntries: Word;
-    NumberOfIdEntries: Word;
-  end;
-  TImageResourceDirectoryEntry = packed record
-    Id: DWORD;
-    Offset: DWORD;
-  end;
-  TImageResourceDataEntry = packed record
-    OffsetToData: DWORD;
-    Size: DWORD;
-    CodePage: DWORD;
-    Reserved: DWORD;
-  end;
-
-procedure Error(const Msg: String);
-begin
-  raise Exception.Create('Resource update error: ' + Msg);
-end;
-
-function SeekToPEHeader(const F: TCustomFile): Boolean;
-var
-  DosHeader: packed record
-    Sig: array[0..1] of AnsiChar;
-    Other: array[0..57] of Byte;
-    PEHeaderOffset: LongWord;
-  end;
-  Sig: DWORD;
-begin
-  Result := False;
-  F.Seek(0);
-  if F.Read(DosHeader, SizeOf(DosHeader)) = SizeOf(DosHeader) then begin
-    if (DosHeader.Sig[0] = 'M') and (DosHeader.Sig[1] = 'Z') and
-       (DosHeader.PEHeaderOffset <> 0) then begin
-      F.Seek(DosHeader.PEHeaderOffset);
-      if F.Read(Sig, SizeOf(Sig)) = SizeOf(Sig) then
-        if Sig = IMAGE_NT_SIGNATURE then
-          Result := True;
-    end;
-  end;
-end;
-
-function SeekToAndReadPEOptionalHeader(const F: TCustomFile;
-  var OptHeader: TImageOptionalHeader; var OptHeaderOffset: Int64): Boolean;
-var
-  Header: TImageFileHeader;
-begin
-  Result := False;
-  if SeekToPEHeader(F) then begin
-    if (F.Read(Header, SizeOf(Header)) = SizeOf(Header)) and
-       (Header.SizeOfOptionalHeader = SizeOf(OptHeader)) then begin
-      OptHeaderOffset := F.Position;
-      if F.Read(OptHeader, SizeOf(OptHeader)) = SizeOf(OptHeader) then
-        if OptHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC then
-          Result := True;
-    end;
-  end;
-end;
-
-function SeekToAndReadPEOptionalHeader64(const F: TCustomFile;
-  var OptHeader: TImageOptionalHeader64; var OptHeaderOffset: Int64): Boolean;
-var
-  Header: TImageFileHeader;
-begin
-  Result := False;
-  if SeekToPEHeader(F) then begin
-    if (F.Read(Header, SizeOf(Header)) = SizeOf(Header)) and
-       (Header.SizeOfOptionalHeader = SizeOf(OptHeader)) then begin
-      OptHeaderOffset := F.Position;
-      if F.Read(OptHeader, SizeOf(OptHeader)) = SizeOf(OptHeader) then
-        if OptHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC then
-          Result := True;
-    end;
-  end;
-end;
-
-procedure FindResourceSection(const F: TCustomFile;
-  var SectionVirtualAddr, SectionPhysOffset, SectionPhysSize: Cardinal);
-var
-  EXESig: Word;
-  PEHeaderOffset, PESig: Cardinal;
-  PEHeader: TImageFileHeader;
-  PEOptHeader: TImageOptionalHeader;
-  PESectionHeader: TImageSectionHeader;
-  I: Integer;
-begin
-  { Read DOS header }
-  F.Seek(0);
-  F.ReadBuffer(EXESig, SizeOf(EXESig));
-  if EXESig <> $5A4D {'MZ'} then
-    Error('File isn''t an EXE file (1)');
-  F.Seek($3C);
-  F.ReadBuffer(PEHeaderOffset, SizeOf(PEHeaderOffset));
-  if PEHeaderOffset = 0 then
-    Error('File isn''t a PE file (1)');
-
-  { Read PE header & optional header }
-  F.Seek(PEHeaderOffset);
-  F.ReadBuffer(PESig, SizeOf(PESig));
-  if PESig <> $00004550 {'PE'#0#0} then
-    Error('File isn''t a PE file (2)');
-  F.ReadBuffer(PEHeader, SizeOf(PEHeader));
-  if PEHeader.SizeOfOptionalHeader <> SizeOf(PEOptHeader) then
-    Error('File isn''t a PE file (3)');
-  F.ReadBuffer(PEOptHeader, SizeOf(PEOptHeader));
-  if PEOptHeader.Magic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC then
-    Error('File isn''t a PE file (4)');
-
-  { Scan section headers for resource section }
-  if (PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = 0) or
-     (PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = 0) then
-    Error('No resources (1)');
-  SectionVirtualAddr := PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
-  SectionPhysOffset := 0;
-  for I := 0 to PEHeader.NumberOfSections-1 do begin
-    F.ReadBuffer(PESectionHeader, SizeOf(PESectionHeader));
-    if (PESectionHeader.VirtualAddress = SectionVirtualAddr) and
-       (PESectionHeader.SizeOfRawData <> 0) then begin
-      SectionPhysOffset := PESectionHeader.PointerToRawData;
-      SectionPhysSize := PESectionHeader.SizeOfRawData;
-      Break;
-    end;
-  end;
-  if SectionPhysOffset = 0 then
-    Error('No resources (2)');
-end;
-
-function FindResOffset(const F: TCustomFile; const AnyId: Boolean;
-  const Id: Cardinal; const FindSubdir: Boolean; var Offset: Cardinal): Boolean;
-var
-  Dir: TImageResourceDirectory;
-  Entry: TImageResourceDirectoryEntry;
-  I: Integer;
-begin
-  F.ReadBuffer(Dir, SizeOf(Dir));
-  { Skip over named entries }
-  for I := 0 to Dir.NumberOfNamedEntries-1 do
-    F.ReadBuffer(Entry, SizeOf(Entry));
-  { Now process ID entries }
-  Result := False;
-  for I := 0 to Dir.NumberOfIdEntries-1 do begin
-    F.ReadBuffer(Entry, SizeOf(Entry));
-    if (AnyId or (Entry.Id = Id)) and
-       ((Entry.Offset and $80000000 <> 0) = FindSubdir) then begin
-      Offset := Entry.Offset and $7FFFFFFF;
-      Result := True;
-      Break;
-    end;
-  end;
-end;
-
-function SeekToResourceData(const F: TCustomFile; const ResType, ResId: Cardinal): Cardinal;
-{ Seeks to the specified resource's data, and returns its size. Raises an
-  exception if the resource cannot be found. }
-var
-  SectionVirtualAddr, SectionPhysOffset, SectionPhysSize, Ofs: Cardinal;
-  DataEntry: TImageResourceDataEntry;
-begin
-  FindResourceSection(F, SectionVirtualAddr, SectionPhysOffset, SectionPhysSize);
-
-  { Scan the resource directory }
-  F.Seek(SectionPhysOffset);
-  if not FindResOffset(F, False, ResType, True, Ofs) then
-    Error('Can''t find resource (1)');
-  F.Seek(SectionPhysOffset + Ofs);
-  if not FindResOffset(F, False, ResId, True, Ofs) then
-    Error('Can''t find resource (2)');
-  F.Seek(SectionPhysOffset + Ofs);
-  if not FindResOffset(F, True, 0, False, Ofs) then
-    Error('Can''t find resource (3).');
-  F.Seek(SectionPhysOffset + Ofs);
-  F.ReadBuffer(DataEntry, SizeOf(DataEntry));
-
-  { Sanity check: DataEntry.OffsetToData is an RVA. It's technically possible
-    for the RVA to point to a different section, but we don't support that. }
-  if Cardinal(DataEntry.OffsetToData) < SectionVirtualAddr then
-    Error('Invalid resource (1)');
-  if Cardinal(DataEntry.OffsetToData - SectionVirtualAddr + DataEntry.Size) > SectionPhysSize then
-    Error('Invalid resource (2)');
-
-  { Seek to the resource }
-  F.Seek(SectionPhysOffset + (DataEntry.OffsetToData - SectionVirtualAddr));
-  Result := DataEntry.Size;
-end;
-
-procedure UpdateManifestRequestedExecutionLevel(const F: TCustomFile;
-  const RequireAdministrator: Boolean);
-const
-  ElementText: AnsiString = '<requestedExecutionLevel level="';
-  Levels: array[Boolean] of AnsiString = (
-    'highestAvailable"    ',
-    'requireAdministrator"');
-var
-  S: AnsiString;
-  P: Integer;
-begin
-  { Read the manifest resource into a string }
-  SetString(S, nil, SeekToResourceData(F, 24, 1));
-  var Offset := F.Position;
-  F.ReadBuffer(S[1], Length(S));
-
-  { Locate and update the requestedExecutionLevel element }
-  P := Pos(ElementText, S);
-  if P = 0 then
-    Error('Element not found');
-  Inc(P, Length(ElementText));
-  if Copy(S, P+21, 10) <> ' uiAccess=' then
-    Error('Level too short');
-  Inc(Offset, P-1);
-  F.Seek(Offset);
-  F.WriteAnsiString(Levels[RequireAdministrator]);
-end;
-
-function ReadSignatureAndChecksumFields(const F: TCustomFile;
-  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
-{ Reads the signature and checksum fields in the specified file's header.
-  If the file is not a valid PE32 executable, False is returned. }
-var
-  OptHeader: TImageOptionalHeader;
-  OptHeaderOffset: Int64;
-begin
-  Result := SeekToAndReadPEOptionalHeader(F, OptHeader, OptHeaderOffset);
-  if Result then begin
-    ASignatureAddress := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
-    ASignatureSize := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-    AChecksum := OptHeader.CheckSum;
-  end;
-end;
-
-function ReadSignatureAndChecksumFields64(const F: TCustomFile;
-  var ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
-{ Reads the signature and checksum fields in the specified file's header.
-  If the file is not a valid PE32+ executable, False is returned. }
-var
-  OptHeader: TImageOptionalHeader64;
-  OptHeaderOffset: Int64;
-begin
-  Result := SeekToAndReadPEOptionalHeader64(F, OptHeader, OptHeaderOffset);
-  if Result then begin
-    ASignatureAddress := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
-    ASignatureSize := OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-    AChecksum := OptHeader.CheckSum;
-  end;
-end;
-
-function UpdateSignatureAndChecksumFields(const F: TCustomFile;
-  const ASignatureAddress, ASignatureSize, AChecksum: DWORD): Boolean;
-{ Sets the signature and checksum fields in the specified file's header.
-  If the file is not a valid PE32 executable, False is returned. }
-var
-  OptHeader: TImageOptionalHeader;
-  OptHeaderOffset: Int64;
-begin
-  Result := SeekToAndReadPEOptionalHeader(F, OptHeader, OptHeaderOffset);
-  if Result then begin
-    OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress := ASignatureAddress;
-    OptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size := ASignatureSize;
-    OptHeader.CheckSum := AChecksum;
-    F.Seek(OptHeaderOffset);
-    F.WriteBuffer(OptHeader, SizeOf(OptHeader));
-  end;
-end;
-
-end.