mirror of
https://github.com/fast4x/datalock.git
synced 2025-06-05 21:49:16 +02:00
Initial Commit
This commit is contained in:
182
UPayload.pas
Normal file
182
UPayload.pas
Normal file
@ -0,0 +1,182 @@
|
||||
unit UPayload;
|
||||
|
||||
{$MODE Delphi}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TPayload = class(TObject)
|
||||
private
|
||||
fFileName: string;
|
||||
fOldFileMode: Integer;
|
||||
fFile: File;
|
||||
procedure Open(Mode: Integer);
|
||||
procedure Close;
|
||||
public
|
||||
constructor Create(const FileName: string);
|
||||
function HasPayload: Boolean;
|
||||
function PayloadSize: Integer;
|
||||
procedure SetPayload(const Data; const DataSize: Integer);
|
||||
procedure GetPayload(var Data);
|
||||
procedure RemovePayload;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
ActiveX;
|
||||
|
||||
type
|
||||
TPayloadFooter = packed record
|
||||
WaterMark: TGUID;
|
||||
ExeSize: LongInt;
|
||||
DataSize: LongInt;
|
||||
end;
|
||||
|
||||
const
|
||||
cWaterMarkGUID: TGUID =
|
||||
'{9FABA105-EDA8-45C3-89F4-369315A947EB}';
|
||||
cReadOnlyMode = 0;
|
||||
cReadWriteMode = 2;
|
||||
|
||||
procedure InitFooter(out Footer: TPayloadFooter);
|
||||
begin
|
||||
FillChar(Footer, SizeOf(Footer), 0);
|
||||
Footer.WaterMark := cWaterMarkGUID;
|
||||
end;
|
||||
|
||||
function ReadFooter(var F: File;
|
||||
out Footer: TPayloadFooter): Boolean;
|
||||
var
|
||||
FileLen: Integer;
|
||||
begin
|
||||
// Check that file is large enough for a footer!
|
||||
FileLen := FileSize(F);
|
||||
if FileLen > SizeOf(Footer) then
|
||||
begin
|
||||
// Big enough: move to start of footer and read it
|
||||
Seek(F, FileLen - SizeOf(Footer));
|
||||
BlockRead(F, Footer, SizeOf(Footer));
|
||||
end
|
||||
else
|
||||
// File not large enough for footer: zero it
|
||||
// .. this ensures watermark is invalid
|
||||
FillChar(Footer, SizeOf(Footer), 0);
|
||||
// Return if watermark is valid
|
||||
Result := IsEqualGUID(Footer.WaterMark, cWaterMarkGUID);
|
||||
end;
|
||||
|
||||
procedure TPayload.Close;
|
||||
begin
|
||||
// close file and restores previous file mode
|
||||
CloseFile(fFile);
|
||||
FileMode := fOldFileMode;
|
||||
end;
|
||||
|
||||
constructor TPayload.Create(const FileName: string);
|
||||
begin
|
||||
inherited Create;
|
||||
fFileName := FileName;
|
||||
end;
|
||||
|
||||
procedure TPayload.GetPayload(var Data);
|
||||
var
|
||||
Footer: TPayloadFooter;
|
||||
begin
|
||||
// open file as read only
|
||||
Open(cReadOnlyMode);
|
||||
try
|
||||
// read footer
|
||||
if ReadFooter(fFile, Footer)
|
||||
and (Footer.DataSize > 0) then
|
||||
begin
|
||||
// move to end of exe code and read data
|
||||
Seek(fFile, Footer.ExeSize);
|
||||
BlockRead(fFile, Data, Footer.DataSize);
|
||||
end;
|
||||
finally
|
||||
// close file
|
||||
Close;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPayload.HasPayload: Boolean;
|
||||
begin
|
||||
// we have a payload if size is greater than 0
|
||||
Result := PayloadSize > 0;
|
||||
end;
|
||||
|
||||
procedure TPayload.Open(Mode: Integer);
|
||||
begin
|
||||
// open file with given mode, recording current one
|
||||
fOldFileMode := FileMode;
|
||||
AssignFile(fFile, fFileName);
|
||||
FileMode := Mode;
|
||||
Reset(fFile, 1);
|
||||
end;
|
||||
|
||||
function TPayload.PayloadSize: Integer;
|
||||
var
|
||||
Footer: TPayloadFooter;
|
||||
begin
|
||||
// open file and assume no data
|
||||
Result := 0;
|
||||
Open(cReadOnlyMode);
|
||||
try
|
||||
// read footer and if valid return data size
|
||||
if ReadFooter(fFile, Footer) then
|
||||
Result := Footer.DataSize;
|
||||
finally
|
||||
Close;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPayload.RemovePayload;
|
||||
var
|
||||
PLSize: Integer;
|
||||
FileLen: Integer;
|
||||
begin
|
||||
// get size of payload
|
||||
PLSize := PayloadSize;
|
||||
if PLSize > 0 then
|
||||
begin
|
||||
// we have payload: open file and get size
|
||||
Open(cReadWriteMode);
|
||||
FileLen := FileSize(fFile);
|
||||
try
|
||||
// seek to end of exec code an truncate file there
|
||||
Seek(fFile, FileLen - PLSize - SizeOf(TPayloadFooter));
|
||||
Truncate(fFile);
|
||||
finally
|
||||
Close;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPayload.SetPayload(const Data;
|
||||
const DataSize: Integer);
|
||||
var
|
||||
Footer: TPayloadFooter;
|
||||
begin
|
||||
// remove any existing payload
|
||||
RemovePayload;
|
||||
if DataSize > 0 then
|
||||
begin
|
||||
// we have some data: open file for writing
|
||||
Open(cReadWriteMode);
|
||||
try
|
||||
// create a new footer with required data
|
||||
InitFooter(Footer);
|
||||
Footer.ExeSize := FileSize(fFile);
|
||||
Footer.DataSize := DataSize;
|
||||
// write data and footer at end of exe code
|
||||
Seek(fFile, Footer.ExeSize);
|
||||
BlockWrite(fFile, Data, DataSize);
|
||||
BlockWrite(fFile, Footer, SizeOf(Footer));
|
||||
finally
|
||||
Close;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
Reference in New Issue
Block a user