
move the processlist function from cefuncproc to it's own unit start work on the jni library for java
247 lines
6.2 KiB
ObjectPascal
247 lines
6.2 KiB
ObjectPascal
unit RemoteMemoryManager;
|
|
|
|
{
|
|
this unit will contain a class that will be used to control remotely allocated memory blocks.
|
|
Specifically designed for smaller allocations. allocate at least systeminfo.dwAllocationGranularity on each real alloc (64kb)
|
|
|
|
Speed is not of essence here. Assumed it that only up to 8KB of memory will be used at MOST
|
|
|
|
}
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
windows, syncobjs, Classes, SysUtils, cefuncproc, newkernelhandler;
|
|
|
|
type
|
|
TAllocs=record //record describing each little allocated block of memory
|
|
address: ptruint;
|
|
size: dword;
|
|
end;
|
|
PAllocs=^TAllocs;
|
|
|
|
type
|
|
TAllocatedRegion=record
|
|
remotebase: ptruint; //size is not stored, that is systeminfo.dwAllocationGranularity
|
|
allocs: Tlist; //sorted list of allocations
|
|
end;
|
|
PAllocatedRegion=^TAllocatedRegion;
|
|
|
|
type
|
|
TRemoteMemoryManager=class(tobject)
|
|
private
|
|
cs: TCriticalsection;
|
|
allocatedRegions: Tlist;
|
|
bigAllocs: Tlist;
|
|
function findFreeRegion(size: dword): ptruint;
|
|
procedure addNewAlloc(address: ptruint; size: integer);
|
|
public
|
|
|
|
function alloc(size: dword):ptruint;
|
|
procedure dealloc(address: ptruint);
|
|
constructor create;
|
|
destructor destroy; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses ProcessHandlerUnit;
|
|
|
|
procedure TRemoteMemoryManager.addNewAlloc(address: ptruint; size: integer);
|
|
var i,j: integer;
|
|
a,b: PAllocs;
|
|
ar: PAllocatedRegion;
|
|
begin
|
|
getmem(a, sizeof(TAllocs));
|
|
a.address:=address;
|
|
a.size:=size;
|
|
|
|
for i:=0 to allocatedRegions.count-1 do
|
|
begin
|
|
ar:=PAllocatedRegion(allocatedRegions[i]);
|
|
if InRangeQ(address, ar.remotebase, ar.remotebase+systeminfo.dwAllocationGranularity) then
|
|
begin
|
|
for j:=0 to ar.allocs.Count-1 do
|
|
begin
|
|
b:=PAllocs(ar.allocs[j]);
|
|
if b.address>address then //insert the address before this one
|
|
begin
|
|
ar.allocs.Insert(j,a);
|
|
exit; //inserted the alloc data. leave now
|
|
end;
|
|
end;
|
|
|
|
//still here, add it to the end
|
|
ar.allocs.Add(a);
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TRemoteMemoryManager.findFreeRegion(size: dword): ptruint;
|
|
var i,j: integer;
|
|
currentTry: ptruint;
|
|
a: PAllocs;
|
|
ar: PAllocatedRegion;
|
|
begin
|
|
result:=0;
|
|
|
|
//scan the regions for a gap of at least size bytes
|
|
for i:=0 to allocatedRegions.count-1 do
|
|
begin
|
|
ar:=PAllocatedRegion(allocatedRegions[i]);
|
|
currentTry:=ar.remotebase;
|
|
for j:=0 to ar.allocs.count-1 do
|
|
begin
|
|
a:=PAllocs(ar.allocs[j]); //keep in mind: sorted list
|
|
if ((currentTry+size)>=a.address) then //too big to be used here
|
|
currentTry:=qword(a.address)+a.size //not usable, try the next block
|
|
else //this block seems usable
|
|
break; //this block seems usable
|
|
|
|
end;
|
|
|
|
//check if we're not outside of the allocated region
|
|
if (currentTry+size)<(ar.remotebase+ systeminfo.dwAllocationGranularity) then //found a usable block that falls within a allocated region
|
|
begin
|
|
result:=currentTry;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
function TRemoteMemoryManager.alloc(size: dword):ptruint;
|
|
var i: integer;
|
|
ar: PAllocatedRegion;
|
|
begin
|
|
result:=0;
|
|
if size=0 then exit;
|
|
|
|
//make it so size is always at least dividable by 4 (means min size is 4)
|
|
|
|
i:=size mod 4;
|
|
if i>0 then
|
|
size:=size + (4-i);
|
|
|
|
|
|
if size>=systeminfo.dwAllocationGranularity then //can't be handled with the small handler
|
|
begin
|
|
result:=ptruint(VirtualAllocEx(processhandle,nil,size,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE));
|
|
if result<>0 then
|
|
begin
|
|
cs.enter;
|
|
bigAllocs.Add(pointer(result));
|
|
cs.leave;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
//small enough
|
|
cs.enter;
|
|
try
|
|
result:=findFreeRegion(size);
|
|
|
|
if result=0 then
|
|
begin
|
|
//no free region found
|
|
result:=ptruint(VirtualAllocEx(processhandle,nil,systeminfo.dwAllocationGranularity,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE));
|
|
if result<>0 then
|
|
begin
|
|
ar:=getmem(sizeof(TAllocatedRegion));
|
|
ar.remotebase:=result;
|
|
ar.allocs:=tlist.create;
|
|
allocatedRegions.Add(ar);
|
|
end;
|
|
end;
|
|
|
|
addNewAlloc(result, size);
|
|
|
|
|
|
finally
|
|
cs.leave;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TRemoteMemoryManager.dealloc(address: ptruint);
|
|
var i,j: integer;
|
|
ar: PAllocatedRegion;
|
|
b: PAllocs;
|
|
begin
|
|
cs.enter;
|
|
try
|
|
for i:=0 to allocatedRegions.count-1 do
|
|
begin
|
|
ar:=PAllocatedRegion(allocatedRegions[i]);
|
|
if InRangeQ(address, ar.remotebase, ar.remotebase+systeminfo.dwAllocationGranularity) then
|
|
begin
|
|
for j:=0 to ar.allocs.Count-1 do
|
|
begin
|
|
b:=PAllocs(ar.allocs[j]);
|
|
if address=b.address then //insert the address before this one
|
|
begin
|
|
//found it
|
|
freemem(b);
|
|
ar.allocs.Delete(j);
|
|
|
|
if ar.allocs.Count=0 then //completely freed this region
|
|
begin
|
|
virtualfreeex(processhandle,pointer(ar.remotebase),0,MEM_RELEASE);
|
|
ar.allocs.Free;
|
|
freemem(ar);
|
|
allocatedRegions.Delete(i);
|
|
end;
|
|
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
//not found, check the big alloc region
|
|
i:=bigallocs.IndexOf(pointer(address));
|
|
if i<>-1 then
|
|
begin
|
|
virtualfreeex(processhandle,pointer(address),0,MEM_RELEASE);
|
|
bigallocs.Delete(i);
|
|
end;
|
|
|
|
finally
|
|
cs.leave;
|
|
end;
|
|
end;
|
|
|
|
constructor TRemoteMemoryManager.create;
|
|
begin
|
|
cs:=TCriticalsection.create;
|
|
allocatedRegions:=tlist.create;
|
|
bigallocs:=Tlist.create;
|
|
end;
|
|
|
|
destructor TRemoteMemoryManager.destroy;
|
|
var i,j: integer;
|
|
begin
|
|
//don't dealloc the memory, but do free the structures allocated here
|
|
for i:=0 to allocatedRegions.count-1 do
|
|
begin
|
|
for j:=0 to PAllocatedRegion(allocatedRegions[i]).allocs.Count-1 do
|
|
freemem(PAllocatedRegion(allocatedRegions[i]).allocs[j]);
|
|
|
|
PAllocatedRegion(allocatedRegions[i]).allocs.Free;
|
|
freemem(allocatedRegions[i]);
|
|
end;
|
|
|
|
allocatedRegions.free;
|
|
bigallocs.free;
|
|
|
|
cs.free;
|
|
end;
|
|
|
|
end.
|
|
|