📄 jclsysutils.pas
字号:
end;
end;
{$ENDIF LINUX}
function WriteProtectedMemory(BaseAddress, Buffer: Pointer;
Size: Cardinal; out WrittenBytes: Cardinal): Boolean;
{$IFDEF MSWINDOWS}
begin
Result := WriteProcessMemory(GetCurrentProcess, BaseAddress, Buffer, Size, WrittenBytes);
end;
{$ENDIF MSWINDOWS}
{$IFDEF LINUX}
{ TODO -cHelp : Author: Andreas Hausladen }
{ TODO : Works so far, but causes app to hang on termination }
var
AlignedAddress: Cardinal;
PageSize, ProtectSize: Cardinal;
begin
Result := False;
WrittenBytes := 0;
PageSize := Cardinal(getpagesize);
AlignedAddress := Cardinal(BaseAddress) and not (PageSize - 1); // start memory page
// get the number of needed memory pages
ProtectSize := PageSize;
while Cardinal(BaseAddress) + Size > AlignedAddress + ProtectSize do
Inc(ProtectSize, PageSize);
if mprotect(Pointer(AlignedAddress), ProtectSize,
PROT_READ or PROT_WRITE or PROT_EXEC) = 0 then // obtain write access
begin
try
Move(Buffer^, BaseAddress^, Size); // replace code
Result := True;
WrittenBytes := Size;
finally
// Is there any function that returns the current page protection?
// mprotect(p, ProtectSize, PROT_READ or PROT_EXEC); // lock memory page
end;
end;
end;
procedure FlushInstructionCache;
{ TODO -cHelp : Author: Andreas Hausladen }
begin
// do nothing
end;
{$ENDIF LINUX}
// Guards
type
TSafeGuard = class(TInterfacedObject, ISafeGuard)
private
FItem: Pointer;
public
constructor Create(Mem: Pointer);
destructor Destroy; override;
function ReleaseItem: Pointer;
function GetItem: Pointer;
procedure FreeItem; virtual;
end;
TObjSafeGuard = class(TSafeGuard, ISafeGuard)
public
constructor Create(Obj: TObject);
procedure FreeItem; override;
end;
TMultiSafeGuard = class(TInterfacedObject, IMultiSafeGuard)
private
FItems: TList;
public
constructor Create;
destructor Destroy; override;
function AddItem(Mem: Pointer): Pointer;
procedure FreeItem(Index: Integer); virtual;
function GetCount: Integer;
function GetItem(Index: Integer): Pointer;
function ReleaseItem(Index: Integer): Pointer;
end;
TObjMultiSafeGuard = class(TMultiSafeGuard, IMultiSafeGuard)
public
procedure FreeItem(Index: Integer); override;
end;
//=== { TSafeGuard } =========================================================
constructor TSafeGuard.Create(Mem: Pointer);
begin
inherited Create;
FItem := Mem;
end;
destructor TSafeGuard.Destroy;
begin
FreeItem;
inherited Destroy;
end;
function TSafeGuard.ReleaseItem: Pointer;
begin
Result := FItem;
FItem := nil;
end;
function TSafeGuard.GetItem: Pointer;
begin
Result := FItem;
end;
procedure TSafeGuard.FreeItem;
begin
if FItem <> nil then
FreeMem(FItem);
FItem := nil;
end;
//=== { TObjSafeGuard } ======================================================
constructor TObjSafeGuard.Create(Obj: TObject);
begin
inherited Create(Pointer(Obj));
end;
procedure TObjSafeGuard.FreeItem;
begin
if FItem <> nil then
begin
TObject(FItem).Free;
FItem := nil;
end;
end;
//=== { TMultiSafeGuard } ====================================================
constructor TMultiSafeGuard.Create;
begin
inherited Create;
FItems := TList.Create;
end;
destructor TMultiSafeGuard.Destroy;
var
I: Integer;
begin
for I := FItems.Count - 1 downto 0 do FreeItem(I);
FItems.Free;
inherited Destroy;
end;
function TMultiSafeGuard.AddItem(Mem: Pointer): Pointer;
begin
Result := Mem;
FItems.Add(Mem);
end;
procedure TMultiSafeGuard.FreeItem(Index: Integer);
begin
FreeMem(FItems[Index]);
FItems.Delete(Index);
end;
function TMultiSafeGuard.GetCount: Integer;
begin
Result := FItems.Count;
end;
function TMultiSafeGuard.GetItem(Index: Integer): Pointer;
begin
Result := FItems[Index];
end;
function TMultiSafeGuard.ReleaseItem(Index: Integer): Pointer;
begin
Result := FItems[Index];
FItems.Delete(Index);
end;
function Guard(Mem: Pointer; var SafeGuard: IMultiSafeGuard): Pointer; overload;
begin
if SafeGuard = nil then
SafeGuard := TMultiSafeGuard.Create;
Result := SafeGuard.AddItem(Mem);
end;
//=== { TObjMultiSafeGuard } =================================================
procedure TObjMultiSafeGuard.FreeItem(Index: Integer);
begin
TObject(FItems[Index]).Free;
FItems.Delete(Index);
end;
function Guard(Obj: TObject; var SafeGuard: IMultiSafeGuard): TObject; overload;
begin
if SafeGuard = nil then
SafeGuard := TObjMultiSafeGuard.Create;
Result := SafeGuard.AddItem(Obj);
end;
function Guard(Mem: Pointer; out SafeGuard: ISafeGuard): Pointer; overload;
begin
Result := Mem;
SafeGuard := TSafeGuard.Create(Mem);
end;
function Guard(Obj: TObject; out SafeGuard: ISafeGuard): TObject; overload;
begin
Result := Obj;
SafeGuard := TObjSafeGuard.Create(Obj);
end;
function GuardGetMem(Size: Cardinal; out SafeGuard: ISafeGuard): Pointer;
begin
GetMem(Result, Size);
Guard(Result, SafeGuard);
end;
function GuardAllocMem(Size: Cardinal; out SafeGuard: ISafeGuard): Pointer;
begin
Result := AllocMem(Size);
Guard(Result, SafeGuard);
end;
//=== Binary search ==========================================================
function SearchSortedList(List: TList; SortFunc: TListSortCompare; Item: Pointer; Nearest: Boolean): Integer;
var
L, H, I, C: Integer;
B: Boolean;
begin
Result := -1;
if List <> nil then
begin
L := 0;
H := List.Count - 1;
B := False;
while L <= H do
begin
I := (L + H) shr 1;
C := SortFunc(List.List^[I], Item);
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
begin
B := True;
L := I;
end;
end;
end;
if B then
Result := L
else
if Nearest and (H >= 0) then
Result := H;
end;
end;
function SearchSortedUntyped(Param: Pointer; ItemCount: Integer; SearchFunc: TUntypedSearchCompare;
const Value; Nearest: Boolean): Integer;
var
L, H, I, C: Integer;
B: Boolean;
begin
Result := -1;
if ItemCount > 0 then
begin
L := 0;
H := ItemCount - 1;
B := False;
while L <= H do
begin
I := (L + H) shr 1;
C := SearchFunc(Param, I, Value);
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
begin
B := True;
L := I;
end;
end;
end;
if B then
Result := L
else
if Nearest and (H >= 0) then
Result := H;
end;
end;
//=== Dynamic array sort and search routines =================================
procedure SortDynArray(const ArrayPtr: Pointer; ElementSize: Cardinal; SortFunc: TDynArraySortCompare);
var
TempBuf: TDynByteArray;
function ArrayItemPointer(Item: Integer): Pointer;
begin
Result := Pointer(Cardinal(ArrayPtr) + (Cardinal(Item) * ElementSize));
end;
procedure QuickSort(L, R: Integer);
var
I, J, T: Integer;
P, IPtr, JPtr: Pointer;
begin
repeat
I := L;
J := R;
P := ArrayItemPointer((L + R) shr 1);
repeat
while SortFunc(ArrayItemPointer(I), P) < 0 do
Inc(I);
while SortFunc(ArrayItemPointer(J), P) > 0 do
Dec(J);
if I <= J then
begin
IPtr := ArrayItemPointer(I);
JPtr := ArrayItemPointer(J);
case ElementSize of
SizeOf(Byte):
begin
T := PByte(IPtr)^;
PByte(IPtr)^ := PByte(JPtr)^;
PByte(JPtr)^ := T;
end;
SizeOf(Word):
begin
T := PWord(IPtr)^;
PWord(IPtr)^ := PWord(JPtr)^;
PWord(JPtr)^ := T;
end;
SizeOf(Integer):
begin
T := PInteger(IPtr)^;
PInteger(IPtr)^ := PInteger(JPtr)^;
PInteger(JPtr)^ := T;
end;
else
Move(IPtr^, TempBuf[0], ElementSize);
Move(JPtr^, IPtr^, ElementSize);
Move(TempBuf[0], JPtr^, ElementSize);
end;
if P = IPtr then
P := JPtr
else
if P = JPtr then
P := IPtr;
Inc(I);
Dec(J);
end;
until I > J;
if L < J then
QuickSort(L, J);
L := I;
until I >= R;
end;
begin
if ArrayPtr <> nil then
begin
SetLength(TempBuf, ElementSize);
QuickSort(0, PInteger(Cardinal(ArrayPtr) - 4)^ - 1);
end;
end;
function SearchDynArray(const ArrayPtr: Pointer; ElementSize: Cardinal; SortFunc: TDynArraySortCompare;
ValuePtr: Pointer; Nearest: Boolean): Integer;
var
L, H, I, C: Integer;
B: Boolean;
begin
Result := -1;
if ArrayPtr <> nil then
begin
L := 0;
H := PInteger(Cardinal(ArrayPtr) - 4)^ - 1;
B := False;
while L <= H do
begin
I := (L + H) shr 1;
C := SortFunc(Pointer(Cardinal(ArrayPtr) + (Cardinal(I) * ElementSize)), ValuePtr);
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
begin
B := True;
L := I;
end;
end;
end;
if B then
Result := L
else
if Nearest and (H >= 0) then
Result := H;
end;
end;
{ Various compare functions for basic types }
function DynArrayCompareByte(Item1, Item2: Pointer): Integer;
begin
Result := PByte(Item1)^ - PByte(Item2)^;
end;
function DynArrayCompareShortInt(Item1, Item2: Pointer): Integer;
begin
Result := PShortInt(Item1)^ - PShortInt(Item2)^;
end;
function DynArrayCompareWord(Item1, Item2: Pointer): Integer;
begin
Result := PWord(Item1)^ - PWord(Item2)^;
end;
function DynArrayCompareSmallInt(Item1, Item2: Pointer): Integer;
begin
Result := PSmallInt(Item1)^ - PSmallInt(Item2)^;
end;
function DynArrayCompareInteger(Item1, Item2: Pointer): Integer;
begin
Result := PInteger(Item1)^ - PInteger(Item2)^;
end;
function DynArrayCompareCardinal(Item1, Item2: Pointer): Integer;
begin
Result := PInteger(Item1)^ - PInteger(Item2)^;
end;
function DynArrayCompareInt64(Item1, Item2: Pointer): Integer;
begin
Result := PInt64(Item1)^ - PInt64(Item2)^;
end;
function DynArrayCompareSingle(Item1, Item2: Pointer): Integer;
begin
if PSingle(Item1)^ < PSingle(Item2)^ then
Result := -1
else
if PSingle(Item1)^ > PSingle(Item2)^ then
Result := 1
else
Result := 0;
end;
function DynArrayCompareDouble(Item1, Item2: Pointer): Integer;
begin
if PDouble(Item1)^ < PDouble(Item2)^ then
Result := -1
else
if PDouble(Item1)^ > PDouble(Item2)^ then
Result := 1
else
Result := 0;
end;
function DynArrayCompareExtended(Item1, Item2: Pointer): Integer;
begin
if PExtended(Item1)^ < PExtended(Item2)^ then
Result := -1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -