Skip to content
This repository was archived by the owner on Mar 28, 2025. It is now read-only.

Commit cbade31

Browse files
committed
Repo Update
- Added a basic usage example - Fixed issue with failing to work on Windows 10 - Updated to latest version of perfect-loader
1 parent 929c194 commit cbade31

15 files changed

+2696
-4825
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,7 @@ __recovery/
7979

8080
# Boss dependency manager vendor folder https://github.com/HashLoad/boss
8181
modules/
82+
83+
# MemoryDLL
84+
*.dsv
85+
zip_latest_commit.cmd

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ begin
172172
173173
try
174174
// Attempt to load the DLL from the resource stream.
175-
DLLHandle := LoadMemoryDLL(LResStream.Memory, LResStream.Size());
175+
DLLHandle := LoadMemoryDLL(LResStream.Memory, LResStream.Size;
176176
if DLLHandle = 0 then Exit; // Loading failed.
177177
178178
// Retrieve and initialize any necessary function exports from the DLL.

examples/testbed/TestDLL/TestDLL.dpr

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{===============================================================================
2+
__ __ ___ _ _ ™
3+
| \/ | ___ _ __ ___ _ _ _ _ | \ | | | |
4+
| |\/| |/ -_)| ' \ / _ \| '_|| || || |) || |__ | |__
5+
|_| |_|\___||_|_|_|\___/|_| \_, ||___/ |____||____|
6+
|__/
7+
In-Memory Win64 DLL Loading & Execution for Pascal
8+
9+
Copyright © 2024-present tinyBigGAMES™ LLC
10+
All Rights Reserved.
11+
12+
https://github.com/tinyBigGAMES/MemoryDLL
13+
===============================================================================}
14+
15+
library TestDLL;
16+
17+
{ Important note about DLL memory management: ShareMem must be the
18+
first unit in your library's USES clause AND your project's (select
19+
Project-View Source) USES clause if your DLL exports any procedures or
20+
functions that pass strings as parameters or function results. This
21+
applies to all strings passed to and from your DLL--even those that
22+
are nested in records and classes. ShareMem is the interface unit to
23+
the BORLNDMM.DLL shared memory manager, which must be deployed along
24+
with your DLL. To avoid using BORLNDMM.DLL, pass string information
25+
using PChar or ShortString parameters.
26+
27+
Important note about VCL usage: when this DLL will be implicitly
28+
loaded and this DLL uses TWicImage / TImageCollection created in
29+
any unit initialization section, then Vcl.WicImageInit must be
30+
included into your library's USES clause. }
31+
32+
uses
33+
System.SysUtils,
34+
System.Classes,
35+
UTestDLL in 'UTestDLL.pas';
36+
37+
{$R *.res}
38+
39+
begin
40+
end.

examples/testbed/TestDLL/TestDLL.dproj

+1,120
Large diffs are not rendered by default.

examples/testbed/TestDLL/TestDLL.res

628 Bytes
Binary file not shown.

examples/testbed/TestDLL/UTestDLL.pas

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{===============================================================================
2+
__ __ ___ _ _ ™
3+
| \/ | ___ _ __ ___ _ _ _ _ | \ | | | |
4+
| |\/| |/ -_)| ' \ / _ \| '_|| || || |) || |__ | |__
5+
|_| |_|\___||_|_|_|\___/|_| \_, ||___/ |____||____|
6+
|__/
7+
In-Memory Win64 DLL Loading & Execution for Pascal
8+
9+
Copyright © 2024-present tinyBigGAMES™ LLC
10+
All Rights Reserved.
11+
12+
https://github.com/tinyBigGAMES/MemoryDLL
13+
===============================================================================}
14+
15+
unit UTestDLL;
16+
17+
interface
18+
19+
uses
20+
WinApi.Windows;
21+
22+
procedure Test01(); exports Test01;
23+
24+
implementation
25+
26+
procedure Test01();
27+
begin
28+
MessageBox(0, 'This is exported routine Test01()', 'TestDLL', MB_OK);
29+
end;
30+
31+
end.

examples/testbed/Testbed.dpr

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{===============================================================================
2+
__ __ ___ _ _ ™
3+
| \/ | ___ _ __ ___ _ _ _ _ | \ | | | |
4+
| |\/| |/ -_)| ' \ / _ \| '_|| || || |) || |__ | |__
5+
|_| |_|\___||_|_|_|\___/|_| \_, ||___/ |____||____|
6+
|__/
7+
In-Memory Win64 DLL Loading & Execution for Pascal
8+
9+
Copyright © 2024-present tinyBigGAMES™ LLC
10+
All Rights Reserved.
11+
12+
https://github.com/tinyBigGAMES/MemoryDLL
13+
===============================================================================}
14+
15+
program Testbed;
16+
17+
{$APPTYPE CONSOLE}
18+
19+
{$R *.res}
20+
21+
{$R *.dres}
22+
23+
uses
24+
System.SysUtils,
25+
UTestbed in 'UTestbed.pas',
26+
MemoryDLL in '..\..\src\MemoryDLL.pas';
27+
28+
begin
29+
try
30+
// Run imported routine from TestDLL memory DLL.
31+
Test01();
32+
except
33+
on E: Exception do
34+
Writeln(E.ClassName, ': ', E.Message);
35+
end;
36+
end.

examples/testbed/Testbed.dproj

+1,148
Large diffs are not rendered by default.

examples/testbed/Testbed.res

152 KB
Binary file not shown.

examples/testbed/Testbed_Icon.ico

150 KB
Binary file not shown.

examples/testbed/UTestbed.pas

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
{===============================================================================
2+
__ __ ___ _ _ ™
3+
| \/ | ___ _ __ ___ _ _ _ _ | \ | | | |
4+
| |\/| |/ -_)| ' \ / _ \| '_|| || || |) || |__ | |__
5+
|_| |_|\___||_|_|_|\___/|_| \_, ||___/ |____||____|
6+
|__/
7+
In-Memory Win64 DLL Loading & Execution for Pascal
8+
9+
Copyright © 2024-present tinyBigGAMES™ LLC
10+
All Rights Reserved.
11+
12+
https://github.com/tinyBigGAMES/MemoryDLL
13+
===============================================================================}
14+
15+
unit UTestbed;
16+
17+
interface
18+
19+
uses
20+
WinApi.Windows,
21+
System.Classes,
22+
MemoryDLL;
23+
24+
var
25+
Test01: procedure();
26+
27+
implementation
28+
29+
{
30+
This code is an example of using MemoryDLL to load an embedded a DLL directly
31+
from an embedded resource in memory, ensuring that no filesystem access is
32+
required. It includes methods for loading, initializing, and unloading the
33+
DLL. The DLL is loaded from a resource with a GUID name, providing a measure
34+
of security by obfuscating the resource’s identity.
35+
36+
Variables:
37+
- DLLHandle: THandle
38+
- A handle to the loaded DLL. Initialized to 0, indicating the DLL has
39+
not been loaded. It is updated with the handle returned from
40+
LoadLibrary when the DLL is successfullyloaded from memory.
41+
42+
Functions:
43+
- LoadDLL: Boolean
44+
- Loads the DLL from an embedded resource and initializes it by
45+
retrieving necessary exported functions. Returns True if the DLL is
46+
loaded successfully, otherwise False.
47+
48+
- b6eb28fd6ebe48359ef93aef774b78d1: string
49+
- A GUID-named helper function that returns the resource name for the DLL.
50+
This GUID-like name helps avoid easy detection of the resource.
51+
52+
- UnloadDLL: procedure
53+
- Unloads the DLL by freeing the library associated with DLLHandle. Resets
54+
DLLHandle to 0 to indicate the DLL is unloaded.
55+
56+
Initialization:
57+
- The LoadDLL function is called during initialization, and the program will
58+
terminate with code 1 if the DLL fails to load.
59+
60+
Finalization:
61+
- The UnloadDLL procedure is called upon finalization, ensuring the DLL is
62+
unloaded before program termination.
63+
64+
}
65+
66+
var
67+
DLLHandle: THandle = 0; // Global handle to the loaded DLL, 0 when not loaded.
68+
69+
{
70+
LoadDLL
71+
--------
72+
Attempts to load a DLL directly from a resource embedded within the executable
73+
file. This DLL is expected to be stored as an RCDATA resource under a specific
74+
GUID-like name.
75+
76+
Returns:
77+
Boolean - True if the DLL is successfully loaded, False otherwise.
78+
}
79+
function LoadDLL(): Boolean;
80+
var
81+
LResStream: TResourceStream; // Stream to access the DLL data stored in the resource.
82+
83+
{
84+
b6eb28fd6ebe48359ef93aef774b78d1
85+
---------------------------------
86+
Returns the name of the embedded DLL resource. Uses a GUID-like name for
87+
obfuscation.
88+
89+
Returns:
90+
string - The name of the resource containing the DLL data.
91+
}
92+
function b6eb28fd6ebe48359ef93aef774b78d1(): string;
93+
const
94+
// GUID-like resource name for the embedded DLL.
95+
CValue = 'b87deef5bbfd43c3a07379e26f4dec9b';
96+
begin
97+
Result := CValue;
98+
end;
99+
100+
begin
101+
Result := False;
102+
103+
// Check if the DLL is already loaded.
104+
if DLLHandle <> 0 then Exit;
105+
106+
// Ensure the DLL resource exists.
107+
if not Boolean((FindResource(HInstance,
108+
PChar(b6eb28fd6ebe48359ef93aef774b78d1()), RT_RCDATA) <> 0)) then Exit;
109+
110+
// Create a stream for the DLL resource data.
111+
LResStream := TResourceStream.Create(HInstance,
112+
b6eb28fd6ebe48359ef93aef774b78d1(), RT_RCDATA);
113+
114+
try
115+
// Attempt to load the DLL from the resource stream.
116+
DLLHandle := LoadMemoryDLL(LResStream.Memory, LResStream.Size);
117+
if DLLHandle = 0 then Exit; // Loading failed.
118+
119+
// Retrieve and initialize any necessary function exports from the DLL.
120+
Test01 := GetProcAddress(DLLHandle, 'Test01');
121+
122+
Result := True; // Successful load and initialization.
123+
finally
124+
LResStream.Free(); // Release the resource stream.
125+
end;
126+
end;
127+
128+
{
129+
UnloadDLL
130+
---------
131+
Frees the loaded DLL, releasing any resources associated with DLLHandle,
132+
and resets DLLHandle to 0.
133+
}
134+
procedure UnloadDLL();
135+
begin
136+
if DLLHandle <> 0 then
137+
begin
138+
FreeLibrary(DLLHandle); // Unload the DLL.
139+
DLLHandle := 0; // Reset DLLHandle to indicate the DLL is no longer loaded.
140+
end;
141+
end;
142+
143+
initialization
144+
// Attempt to load the DLL upon program startup. Halt execution with error
145+
// code 1 if it fails.
146+
if not LoadDLL() then
147+
begin
148+
Halt(1);
149+
end;
150+
151+
finalization
152+
// Ensure the DLL is unloaded upon program termination.
153+
UnloadDLL();
154+
155+
end.

src/MemoryDLL.groupproj

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2+
<PropertyGroup>
3+
<ProjectGuid>{F768850F-7EF0-4A7B-BD1C-95151B68EFFE}</ProjectGuid>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Projects Include="..\examples\testbed\TestDLL\TestDLL.dproj">
7+
<Dependencies/>
8+
</Projects>
9+
<Projects Include="..\examples\testbed\Testbed.dproj">
10+
<Dependencies/>
11+
</Projects>
12+
</ItemGroup>
13+
<ProjectExtensions>
14+
<Borland.Personality>Default.Personality.12</Borland.Personality>
15+
<Borland.ProjectType/>
16+
<BorlandProject>
17+
<Default.Personality/>
18+
</BorlandProject>
19+
</ProjectExtensions>
20+
<Target Name="TestDLL">
21+
<MSBuild Projects="..\examples\testbed\TestDLL\TestDLL.dproj"/>
22+
</Target>
23+
<Target Name="TestDLL:Clean">
24+
<MSBuild Projects="..\examples\testbed\TestDLL\TestDLL.dproj" Targets="Clean"/>
25+
</Target>
26+
<Target Name="TestDLL:Make">
27+
<MSBuild Projects="..\examples\testbed\TestDLL\TestDLL.dproj" Targets="Make"/>
28+
</Target>
29+
<Target Name="Testbed">
30+
<MSBuild Projects="..\examples\testbed\Testbed.dproj"/>
31+
</Target>
32+
<Target Name="Testbed:Clean">
33+
<MSBuild Projects="..\examples\testbed\Testbed.dproj" Targets="Clean"/>
34+
</Target>
35+
<Target Name="Testbed:Make">
36+
<MSBuild Projects="..\examples\testbed\Testbed.dproj" Targets="Make"/>
37+
</Target>
38+
<Target Name="Build">
39+
<CallTarget Targets="TestDLL;Testbed"/>
40+
</Target>
41+
<Target Name="Clean">
42+
<CallTarget Targets="TestDLL:Clean;Testbed:Clean"/>
43+
</Target>
44+
<Target Name="Make">
45+
<CallTarget Targets="TestDLL:Make;Testbed:Make"/>
46+
</Target>
47+
<Import Project="$(BDS)\Bin\CodeGear.Group.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Group.Targets')"/>
48+
</Project>

0 commit comments

Comments
 (0)