forked from pult/libssh2_delphi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
HVHeaps.pas
147 lines (124 loc) · 3.33 KB
/
HVHeaps.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
unit HVHeaps;
//
// https://github.com/pult/dll_load_delay
// https://bitbucket.org/VadimLV/dll_load_delay
// http://hallvards.blogspot.com/2008/03/tdm8-delayloading-of-dlls.html
//
// Simple wrapper classes around the Win32 Heap functions.
// Written by Hallvard Vassbotn (hallvard@falcon.no), January 1999
//
interface
{$IFDEF WIN32}
{$DEFINE MSWINDOWS}
{$ENDIF}
{$IFDEF WIN64}
{$DEFINE MSWINDOWS}
{$ENDIF}
{$IFDEF MSWINDOWS}
uses
Windows, Types;
{$IFDEF FPC}
{$ALIGN 8} // For packed record
{$MINENUMSIZE 1}
{$ELSE}
{$IFDEF UNICODE}
{$ALIGN 8} // For packed record
{$MINENUMSIZE 1}
{$IF CompilerVersion >= 25.00}{XE4Up}
{$ZEROBASEDSTRINGS OFF}
{$IFEND}
{$ENDIF}
{$ENDIF}
type
// The TPrivateHeap class gives basic memory allocation capability
// The benefit of using this class instead of the native GetMem
// and FreeMem routines, is that the memory pages used will
// be seperate from other allocations. This gives reduced
// fragmentation.
TPrivateHeap = class//(TObject)
private
FHandle: THandle;
FAllocationFlags: DWORD;
function GetHandle: THandle;
public
destructor Destroy; override;
procedure GetMem(var P{: Pointer}; Size: DWORD); virtual;
procedure FreeMem(P: Pointer);
function SizeOfMem(P: Pointer): DWORD;
property Handle: THandle read GetHandle;
property AllocationFlags: DWORD read FAllocationFlags write FAllocationFlags;
end;
// The Code Heap adds the feature of allocating readable/writable
// and executable memory blocks. This allows us to have safe
// run-time generated code while not wasting as much memory
// as calls to VirtualAlloc would have caused, while avoiding
// the pitfalls of changing the protection flags of blocks
// allocated with GetMem.
TCodeHeap = class(TPrivateHeap)
public
procedure GetMem(var P{: Pointer}; Size: DWORD); override;
end;
{$ENDIF MSWINDOWS}
implementation
{$IFDEF MSWINDOWS}
uses
//{$IFDEF VER93} // Delphi2
//D2Support,
//{$ENDIF}
SysUtils;
function Win32Handle(Handle: THandle): THandle;
begin
if Handle = 0 then
//RaiseLastWin32Error;
RaiseLastOsError;
Result := Handle;
end;
function Win32Pointer(P: Pointer): Pointer;
begin
if P = nil then
//RaiseLastWin32Error;
RaiseLastOsError;
Result := P;
end;
{ TPrivateHeap }
destructor TPrivateHeap.Destroy;
begin
if FHandle <> 0 then
begin
Win32Check(Windows.HeapDestroy(FHandle));
FHandle := 0;
end;
inherited Destroy;
end;
procedure TPrivateHeap.FreeMem(P: Pointer);
begin
Win32Check(Windows.HeapFree(Handle, 0, P));
end;
function TPrivateHeap.GetHandle: THandle;
begin
if FHandle = 0 then
FHandle := Win32Handle(Windows.HeapCreate(0, 0, 0));
Result := FHandle;
end;
procedure TPrivateHeap.GetMem(var P{: Pointer}; Size: DWORD);
begin
Pointer(P) := Win32Pointer(Windows.HeapAlloc(Handle, AllocationFlags, Size));
end;
function TPrivateHeap.SizeOfMem(P: Pointer): DWORD;
begin
Result := Windows.HeapSize(Handle, 0, P);
// HeapSize does not set GetLastError, but returns $FFFFFFFF if it fails
if Result = $FFFFFFFF then
Result := 0;
end;
{ TCodeHeap }
procedure TCodeHeap.GetMem(var P{: Pointer}; Size: DWORD);
var
Dummy: DWORD;
begin
inherited GetMem(P, Size);
Win32Check(Windows.VirtualProtect(Pointer(P), Size, PAGE_EXECUTE_READWRITE, @Dummy));
end;
initialization
{$ENDIF MSWINDOWS}
end.