-
Notifications
You must be signed in to change notification settings - Fork 44
/
ModuleLoader.pas
288 lines (241 loc) · 10.6 KB
/
ModuleLoader.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
{******************************************************************}
{ }
{ Project JEDI }
{ OS independent Dynamic Loading Helpers }
{ }
{ The initial developer of the this code is }
{ Robert Marquardt <robert_marquardt@gmx.de) }
{ }
{ Copyright (C) 2000, 2001 Robert Marquardt. }
{ }
{ Obtained through: }
{ Joint Endeavour of Delphi Innovators (Project JEDI) }
{ }
{ You may retrieve the latest version of this file at the Project }
{ JEDI home page, located at http://delphi-jedi.org }
{ }
{ The contents of this file are used with permission, subject to }
{ the Mozilla Public License Version 1.1 (the "License"); you may }
{ not use this file except in compliance with the License. You may }
{ obtain a copy of the License at }
{ http://www.mozilla.org/NPL/NPL-1_1Final.html }
{ }
{ Software distributed under the License is distributed on an }
{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
{ implied. See the License for the specific language governing }
{ rights and limitations under the License. }
{ }
{******************************************************************}
unit ModuleLoader;
interface
{$WEAKPACKAGEUNIT ON}
// each OS gets its own IFDEFed complete code block to make reading easier
{$IFDEF WIN32}
uses
Windows;
type
// Handle to a loaded DLL
TModuleHandle = HINST;
const
// Value designating an unassigned TModuleHandle or a failed loading
INVALID_MODULEHANDLE_VALUE = TModuleHandle(0);
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
procedure UnloadModule(var Module: TModuleHandle);
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
implementation
// load the DLL file FileName
// the rules for FileName are those of LoadLibrary
// Returns: True = success, False = failure to load
// Assigns: the handle of the loaded DLL to Module
// Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
// on entry the function will do nothing but returning success.
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
begin
if Module = INVALID_MODULEHANDLE_VALUE then
Module := LoadLibrary(PChar(FileName));
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// load the DLL file FileName
// LoadLibraryEx is used to get better control of the loading
// for the allowed values for flags see LoadLibraryEx documentation.
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
begin
if Module = INVALID_MODULEHANDLE_VALUE then
Module := LoadLibraryEx(PChar(FileName), 0, Flags);
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// unload a DLL loaded with LoadModule or LoadModuleEx
// The procedure will not try to unload a handle with
// value INVALID_MODULEHANDLE_VALUE and assigns this value
// to Module after unload.
procedure UnloadModule(var Module: TModuleHandle);
begin
if Module <> INVALID_MODULEHANDLE_VALUE then
FreeLibrary(Module);
Module := INVALID_MODULEHANDLE_VALUE;
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the DLL Module
// nil is returned if the symbol is not available
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := GetProcAddress(Module, PChar(SymbolName));
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the DLL Module
// nil is returned if the symbol is not available.
// as an extra the boolean variable Accu is updated
// by anding in the success of the function.
// This is very handy for rendering a global result
// when accessing a long list of symbols.
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := GetProcAddress(Module, PChar(SymbolName));
Accu := Accu and (Result <> nil);
end;
// get the value of variables exported from a DLL Module
// Delphi cannot access variables in a DLL directly, so
// this function allows to copy the data from the DLL.
// Beware! You are accessing the DLL memory image directly.
// Be sure to access a variable not a function and be sure
// to read the correct amount of data.
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Sym^, Buffer, Size);
end;
// set the value of variables exported from a DLL Module
// Delphi cannot access variables in a DLL directly, so
// this function allows to copy the data to the DLL!
// BEWARE! You are accessing the DLL memory image directly.
// Be sure to access a variable not a function and be sure
// to write the correct amount of data.
// The changes are not persistent. They get lost when the
// DLL is unloaded.
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Buffer, Sym^, Size);
end;
{$ENDIF}
{$IFDEF LINUX}
uses
Types, Libc;
type
// Handle to a loaded .so
TModuleHandle = Pointer;
const
// Value designating an unassigned TModuleHandle or a failed loading
INVALID_MODULEHANDLE_VALUE = TModuleHandle(nil);
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
procedure UnloadModule(var Module: TModuleHandle);
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
implementation
// load the .so file FileName
// the rules for FileName are those of dlopen()
// Returns: True = success, False = failure to load
// Assigns: the handle of the loaded .so to Module
// Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
// on entry the function will do nothing but returning success.
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
begin
if Module = INVALID_MODULEHANDLE_VALUE then
Module := dlopen(PChar(FileName), RTLD_NOW);
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// load the .so file FileName
// dlopen() with flags is used to get better control of the loading
// for the allowed values for flags see "man dlopen".
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
begin
if Module = INVALID_MODULEHANDLE_VALUE then
Module := dlopen(PChar(FileName), Flags);
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// unload a .so loaded with LoadModule or LoadModuleEx
// The procedure will not try to unload a handle with
// value INVALID_MODULEHANDLE_VALUE and assigns this value
// to Module after unload.
procedure UnloadModule(var Module: TModuleHandle);
begin
if Module <> INVALID_MODULEHANDLE_VALUE then
dlclose(Module);
Module := INVALID_MODULEHANDLE_VALUE;
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the .so Module
// nil is returned if the symbol is not available
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := dlsym(Module, PChar(SymbolName));
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the .so Module
// nil is returned if the symbol is not available.
// as an extra the boolean variable Accu is updated
// by anding in the success of the function.
// This is very handy for rendering a global result
// when accessing a long list of symbols.
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := dlsym(Module, PChar(SymbolName));
Accu := Accu and (Result <> nil);
end;
// get the value of variables exported from a .so Module
// Delphi cannot access variables in a .so directly, so
// this function allows to copy the data from the .so.
// Beware! You are accessing the .so memory image directly.
// Be sure to access a variable not a function and be sure
// to read the correct amount of data.
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Sym^, Buffer, Size);
end;
// set the value of variables exported from a .so Module
// Delphi cannot access variables in a .so directly, so
// this function allows to copy the data to the .so!
// BEWARE! You are accessing the .so memory image directly.
// Be sure to access a variable not a function and be sure
// to write the correct amount of data.
// The changes are not persistent. They get lost when the
// .so is unloaded.
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Buffer, Sym^, Size);
end;
{$ENDIF}
end.