Thema: Delphi INI in EXE einbinden

Einzelnen Beitrag anzeigen

NicoDE
(Gast)

n/a Beiträge
 

Re: INI in EXE einbinden

  Alt 24. Jun 2005, 20:47
Du kannst die Daten an die Exe anhängen (zum Beispiel mit einem TMemoryStream).
Den Start der anghängten Daten kann man zur Laufzeit anhand des PE/COFF-Headers aus dem Image auslesen.
(so funktioniert das auch bei etlichen selbsextrahierenden Programmen)

Einfacher Weg die Ini an die Exe anzuhängen:
Code:
copy /B Project1.exe + /B Foo.ini Project1Foo.exe
Und zur Laufzeit an die Daten kommen:
Delphi-Quellcode:
unit PE32Stub {platform};

interface

function GetOverlay(var Buffer: Pointer): Cardinal;
procedure FreeOverlay(var Buffer: Pointer);

implementation

uses
  Windows;

// types/defs (mostly Delphi 2/3 stuff)

type
  LONG = Longint;

const
  IMAGE_DOS_SIGNATURE = $5A4D;
type
  TImageDosHeader = packed record
      e_magic : WORD;
      e_cblp : WORD;
      e_cp : WORD;
      e_crlc : WORD;
      e_cparhdr : WORD;
      e_minalloc: WORD;
      e_maxalloc: WORD;
      e_ss : WORD;
      e_sp : WORD;
      e_csum : WORD;
      e_ip : WORD;
      e_cs : WORD;
      e_lfarlc : WORD;
      e_ovno : WORD;
      e_res : array [0..3] of WORD;
      e_oemid : WORD;
      e_oeminfo : WORD;
      e_res2 : array [0..9] of WORD;
      e_lfanew : LONG;
  end;
  TImageFileHeader = packed record
    Machine : WORD;
    NumberOfSections : WORD;
    TimeDateStamp : DWORD;
    PointerToSymbolTable: DWORD;
    NumberOfSymbols : DWORD;
    SizeOfOptionalHeader: WORD;
    Characteristics : WORD;
  end;
const
  IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
  IMAGE_NT_OPTIONAL_HDR_MAGIC = WORD($010B);
type
  TImageDataDirectory = record
    VirtualAddress: DWORD;
    Size : DWORD;
  end;
  TImageOptionalHeader = packed record
    Magic : WORD;
    MajorLinkerVersion : BYTE;
    MinorLinkerVersion : BYTE;
    SizeOfCode : DWORD;
    SizeOfInitializedData : DWORD;
    SizeOfUninitializedData : DWORD;
    AddressOfEntryPoint : DWORD;
    BaseOfCode : DWORD;
    BaseOfData : DWORD;
    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 :
      array [0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1] of TImageDataDirectory;
  end;
const
  IMAGE_NT_SIGNATURE = DWORD($00004550);
type
  TImageNtHeaders = packed record
    Signature : DWORD;
    FileHeader : TImageFileHeader;
    OptionalHeader: TImageOptionalHeader;
  end;
const
  IMAGE_SIZEOF_SHORT_NAME = 8;
type
  TImageSectionHeader = packed record
    Name : array [0..IMAGE_SIZEOF_SHORT_NAME - 1] of AnsiChar;
    Misc : record
      case Integer of
        0: (PhysicalAddress: DWORD);
        1: (VirtualSize : DWORD);
    end;
    VirtualAddress : DWORD;
    SizeOfRawData : DWORD;
    PointerToRawData : DWORD;
    PointerToRelocations : DWORD;
    PointerToLinenumbers : DWORD;
    NumberOfRelocations : WORD;
    NumberOfLinenumbers : WORD;
    Characteristics : DWORD;
  end;

// GetOverlay

function GetOverlay(var Buffer: Pointer): Cardinal;
const
  INVALID_FILE_SIZE = DWORD(-1);
  INVALID_SET_FILE_POINTER = DWORD(-1);
var
  FileName: array [0..MAX_PATH] of Char;
  FileHandle: THandle;
  FileSizeLo: DWORD;
  DosHeader: TImageDosHeader;
  BytesRead: DWORD;
  NtHeaders: TImageNtHeaders;
  Offset: DWORD;
  Section: WORD;
  SecHeader: TImageSectionHeader;
begin
  Result := 0;
  Buffer := nil;
  if GetModuleFileName(HMODULE(nil), FileName, MAX_PATH) <= 0 then
    Exit;
  FileHandle := CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, nil,
    OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, THandle(nil));
  if INVALID_HANDLE_VALUE = FileHandle then
    Exit;
  try
    // Get FileSize
    FileSizeLo := GetFileSize(FileHandle, nil);
    if INVALID_FILE_SIZE = FileSizeLo then
      Exit;
    // Read Headers
    with DosHeader, NtHeaders, NtHeaders.FileHeader, NtHeaders.OptionalHeader do
      if not ReadFile(FileHandle, DosHeader, SizeOf(TImageDosHeader), BytesRead,
          nil) or (BytesRead <> SizeOf(TImageDosHeader)) or
        (e_magic <> IMAGE_DOS_SIGNATURE) or
        (e_lfanew < SizeOf(TImageDosHeader)) or
        (INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle,
          e_lfanew - SizeOf(TImageDosHeader), nil, FILE_CURRENT)) or
        not ReadFile(FileHandle, NtHeaders, SizeOf(TImageNtHeaders), BytesRead,
          nil) or (BytesRead <> SizeOf(TImageNtHeaders)) or
        (Signature <> IMAGE_NT_SIGNATURE) or (NumberOfSections <= 0) or
        (SizeOfOptionalHeader < SizeOf(TImageOptionalHeader)) or
        (INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle,
          SizeOfOptionalHeader - SizeOf(TImageOptionalHeader), nil,
          FILE_CURRENT)) then
        Exit;
    // Read Sections
    Offset := 0;
    for Section := 1 to NtHeaders.FileHeader.NumberOfSections do
    begin
      if not ReadFile(FileHandle, SecHeader, SizeOf(TImageSectionHeader),
        BytesRead, nil) or (BytesRead <> SizeOf(TImageSectionHeader)) then
        Exit;
      if Offset < SecHeader.PointerToRawData + SecHeader.SizeOfRawData then
        Offset := SecHeader.PointerToRawData + SecHeader.SizeOfRawData;
    end;
    if Offset <= 0 then
      Exit;
    Result := FileSizeLo - Offset;
    if Result <= 0 then
      Exit;
    // Get Overlay
    Buffer := VirtualAlloc(nil, Result + 1, MEM_COMMIT, PAGE_READWRITE);
    if not Assigned(Buffer) then
    begin
      Result := 0;
      Exit;
    end;
    try
      if (INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle, Offset, nil,
        FILE_BEGIN)) or
        not ReadFile(FileHandle, Buffer^, Result, BytesRead, nil) or
        (BytesRead <> Result) then
      begin
        VirtualFree(Buffer, 0, MEM_RELEASE);
        Buffer := nil;
        Result := 0;
      end
      else
        PAnsiChar(Buffer)[Result] := #0; // termiating null for strings
    except
      VirtualFree(Buffer, 0, MEM_RELEASE);
      Buffer := nil;
      Result := 0;
    end;
  finally
    CloseHandle(FileHandle);
  end;
end;

procedure FreeOverlay(var Buffer: Pointer);
begin
  if Assigned(Buffer) then
  begin
    VirtualFree(Buffer, 0, MEM_RELEASE);
    Buffer := nil;
  end;
end;

end.
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  Size: Cardinal;
  Buff: Pointer;
  StrLst: TStringList;
  Stream: TMemoryStream;
begin
  Size := GetOverlay(Buff);
  if Assigned(Buff) then
    try
      StrLst := TStringList.Create;
      Stream := TMemoryStream.Create;
      try
        Stream.WriteBuffer(Buff^, Size);
        Stream.Position := 0;
        StrLst.LoadFromStream(Stream);
        // TMemIniFile.SetStrings(StrLst);
        Memo1.Lines.Text := StrLst.Text;
      finally
        StrLst.Free;
        Stream.Free;
      end;
    finally
      FreeOverlay(Buff);
    end;
end;
  Mit Zitat antworten Zitat