{ --------------------------------------------------------------------------- }
function MapFile
(
const InFilename : pchar;
out OutMapAddress : pointer;
out OutModuleSize : DWORD
)
: boolean;
{ maps a file (should be a PE file) }
{ NOTE: could use VirtualAlloc instead of a mapping (it would simplify the }
{ function) }
var
FileHandle : THANDLE = INVALID_HANDLE_VALUE;
FileSize : int64 = 0;
BytesRead : DWORD = 0;
MappingHandle : THANDLE = 0;
begin
result := FALSE;
OutMapAddress := nil;
OutModuleSize := 0;
repeat { scope - not a loop }
{ open the file to obtain a handle to it }
FileHandle := CreateFileA(InFilename,
GENERIC_READ,
FILE_SHARE_READ,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if FileHandle = INVALID_HANDLE_VALUE then
begin
writeln('MapFile: CreateFile failed');
break;
end;
if not GetFileSizeEx(FileHandle, @FileSize) then
begin
writeln('MapFile: GetFileSizeEx failed.');
break;
end;
{ the addition of a page (4 * 1024) is to ensure the file is null }
{ terminated and there is extra room which allows testing characters past }
{ what would have been the eof. }
{ However, note that the extra room is not used, it's there only to }
{ ensure string comparisons can go past the original end of file without }
{ causing an access violation. Therefore, while the extra room is not }
{ used it is required for the program to operate properly. }
MappingHandle := CreateFileMappingA(INVALID_HANDLE_VALUE,
nil, { no security }
PAGE_READWRITE,
0, { size high }
FileSize + (4 * 1024), { size low }
nil);
if MappingHandle = 0 then
begin
writeln('MapFile: CreateFileMapping failed.');
break;
end;
{ commit linear address space to the file mapping }
OutMapAddress := MapViewOfFile(MappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if OutMapAddress = nil then
begin
writeln('MapFile: MapViewOfFile failed.');
break;
if IsDebuggerPresent() then
begin
DebugBreak();
end;
end;
{ read the file into the mapping }
if not ReadFile(FileHandle,
OutMapAddress,
FileSize,
@BytesRead,
nil) then
begin
writeln('MapFile: ReadFile failed.');
BytesRead := 0;
if IsDebuggerPresent() then
begin
DebugBreak();
end;
break;
end;
{ it would be "profilactic" to set the mapping to read only now that the }
{ file has been read into it. }
until TRUE;
{ we no longer need the FileHandle nor the MappingHandle }
if FileHandle <> INVALID_HANDLE_VALUE then CloseHandle(FileHandle);
if MappingHandle <> 0 then CloseHandle(MappingHandle);
if (OutMapAddress <> nil) and
(BytesRead <> 0) then
begin
result := TRUE;
OutModuleSize := FileSize;
end;
end;
{ --------------------------------------------------------------------------- }
function UnmapFile(InMapAddress : pointer) : boolean;
{ as its name indicates, it unmaps a previously mapped file }
begin
result := UnmapViewOfFile(InMapAddress);
end;