MiTec/Common/MiTeC_EXEModule.pas
2024-07-06 22:30:25 +02:00

143 lines
3.5 KiB
ObjectPascal

{*******************************************************}
{ MiTeC Common Routines }
{ EXE Module & EXE Resources }
{ }
{ Copyright (c) 2015 Michal Mutl }
{ }
{*******************************************************}
{$INCLUDE Compilers.inc}
unit MiTeC_EXEModule;
interface
uses {$IFDEF RAD9PLUS}
WinAPI.Windows, System.SysUtils, System.Classes;
{$ELSE}
Windows, SysUtils, Classes;
{$ENDIF}
type
TExeModule=class
private
FHandle: HMODULE;
FExeFile: string;
FAutoLoad: Boolean;
function GetIsLoaded: Boolean;
procedure SetExeFile(const Value: string);
public
constructor Create(const AExeFile: string=''; const AAutoLoad: Boolean = True);
procedure AfterConstruction; override;
destructor Destroy; override;
procedure Load;
procedure Unload;
property Handle: HMODULE read FHandle;
property ExeFile: string read FExeFile write SetExeFile;
property IsLoaded: Boolean read GetIsLoaded;
property AutoLoad: Boolean read FAutoLoad;
end;
procedure AlterResource(const AExeFile, AResName: string; const AContent: Pointer; const ASize: Cardinal);
procedure ReadResource(const AExeFile, AResName: string; AStream: TStream);
implementation
procedure AlterResource(const AExeFile, AResName: string; const AContent: Pointer; const ASize: Cardinal);
var
h: THandle;
begin
h:=BeginUpdateResource(PChar(AExeFile),False);
if h=0 then
raise Exception.CreateFmt('Can not update resource of %s'#13#10#13#10'%s.',[AEXEFile,SysErrorMessage(GetLastError)]);
try
if not UpdateResource(h,RT_RCDATA,PChar(UpperCase(AResName)),LANG_NEUTRAL,AContent,ASize) then
raise Exception.CreateFmt('Can not update resource %s of %s.'#13#10#13#10'%s',[AResName,AExeFile,SysErrorMessage(GetLastError)]);
finally
EndUpdateResource(h,False);
end;
end;
procedure ReadResource(const AExeFile, AResName: string; AStream: TStream);
var
rs: TResourceStream;
begin
AStream.Size:=0;
AStream.Position:=0;
with TExeModule.Create(AExeFile) do
try
rs:=TResourceStream.Create(Handle,UpperCase(AResName),RT_RCDATA);
try
AStream.CopyFrom(rs,rs.Size);
finally
rs.Free;
end;
finally
Free;
end;
AStream.Position:=0;
end;
{ TExeModule }
procedure TExeModule.AfterConstruction;
begin
inherited;
if FAutoLoad then
Load;
end;
constructor TExeModule.Create(const AExeFile: string; const AAutoLoad: Boolean);
begin
FExeFile:=AExeFile;
if AAutoLoad then
FAutoLoad:=AAutoLoad;
end;
destructor TExeModule.Destroy;
begin
Unload;
inherited;
end;
function TExeModule.GetIsLoaded: Boolean;
begin
Result:=(FHandle<>0) and (FHandle<>INVALID_HANDLE_VALUE);
end;
procedure TExeModule.Load;
begin
if IsLoaded then
Exit;
if FExeFile='' then
raise Exception.Create('Executable file not specified');
if not FileExists(FExeFile) then
raise Exception.CreateFmt('%s is not found',[FExeFile]);
FHandle:=LoadLibrary(PChar(FExeFile));
if FHandle=0 then
raise Exception.CreateFmt('Can not load %s.'#13#10#13#10'%s',[FExeFile,SysErrorMessage(GetLastError)]);
end;
procedure TExeModule.SetExeFile(const Value: string);
begin
if SameText(FExeFile, Value) then
Exit;
FExeFile:=Value;
Unload;
end;
procedure TExeModule.Unload;
begin
if not IsLoaded then
Exit;
FreeLibrary(FHandle);
FHandle:=0;
end;
end.