function ReadFileToBuffer(const AFileName: string; var AFileSize: Cardinal; var AData): Boolean;
var
FileHandle: THandle;
MappingHandle: THandle;
FindData: TWin32FindData;
MappingName: string;
TheCreationTime: TFileTime;
FileAttrs: DWORD;
ThisSize: Cardinal;
CommitSize: Cardinal;
Segment: Cardinal;
PFileData, PDest: Pointer;
procedure ReleaseMemory;
begin
Windows.VirtualFree(PDest, 0, MEM_RELEASE);
PPointer(@AData)^ := nil;
AFileSize := 0;
end;
function MoveDataTo(ASource, ADest: Pointer; ASize: Cardinal): Boolean;
begin
Result := False;
try
CriticalSectionLock;
try
Windows.VirtualAlloc(PFileData, CommitSize, MEM_COMMIT, PAGE_READONLY);
Windows.VirtualLock(PFileData, CommitSize);
System.Move(ASource^, ADest^, ASize);
finally
Windows.VirtualUnlock(PFileData, CommitSize);
Windows.VirtualFree(PFileData, CommitSize, MEM_DECOMMIT);
CriticalSectionUnlock;
end;
except
on EAccessViolation do
begin
Windows.VirtualUnlock(PFileData, CommitSize);
Windows.VirtualFree(PFileData, CommitSize, MEM_DECOMMIT);
CriticalSectionUnlock;
ReleaseMemory;
Exit;
end;
end;
Result := True;
end;
begin
Result := False;
AFileSize := 0;
FileHandle := Windows.FindFirstFile(PChar(AFileName), FindData);
if FileHandle = INVALID_HANDLE_VALUE then Exit;
ThisSize := FindData.nFileSizeLow;
Windows.FindClose(FileHandle);
FileAttrs := Windows.GetFileAttributes(PChar(AFileName));
if (FileAttrs and FILE_ATTRIBUTE_READONLY) <> 0 then
begin
if not Windows.SetFileAttributes(PChar(AFileName), FileAttrs xor
FILE_ATTRIBUTE_READONLY) then Exit;
end;
if ThisSize = 0 then
begin
Windows.DeleteFile(PChar(AFileName));
Exit;
end;
try
PDest := nil;
PDest := Windows.VirtualAlloc(nil, ThisSize, MEM_COMMIT or MEM_RESERVE,
PAGE_READWRITE);
PFileData := nil;
AFileSize := ThisSize;
PPointer(@AData)^ := PDest;
CommitSize := 0;
while CommitSize < AFileSize do
begin
PByte(PDest)^ := 0;
PDest := Pointer(DWORD(PDest) + $00001000);
Inc(CommitSize, $00001000);
end;
PDest := PPointer(@AData)^;
try
FileHandle := Windows.CreateFile(PChar(AFileName), Const_FileAccess,
Const_FileShare, nil, OPEN_EXISTING, 0, 0);
if FileHandle = INVALID_HANDLE_VALUE then
begin
ReleaseMemory;
Exit;
end;
TheCreationTime := FindData.ftCreationTime;
MappingName := GetFileNameExcludeExt(AFileName) + Format('_%.8x%.8x',
[TheCreationTime.dwHighDateTime, TheCreationTime.dwLowDateTime]);
MappingHandle := Windows.OpenFileMapping(FILE_MAP_ALL_ACCESS, False, PChar
(MappingName));
if not MappingHandle <> 0 then
begin
MappingHandle := Windows.CreateFileMapping(FileHandle, nil, PAGE_READWRITE or
SEC_RESERVE, 0, ThisSize, PChar(MappingName));
if (MappingHandle = 0) or (Windows.GetLastError <> ERROR_SUCCESS) then
begin
ReleaseMemory;
Exit;
end;
end;
Segment := 0;
while ThisSize <> 0 do
begin
if ThisSize and $FFFF0000 > 0 then
begin
PFileData := Windows.MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0,
Segment, $00010000);
if PFileData = nil then
begin
ReleaseMemory;
Exit;
end;
if not MoveDataTo(PFileData, PDest, $00010000) then Exit;
Windows.UnmapViewOfFile(PFileData);
PDest := Pointer(DWORD(PDest) + $00010000);
Segment := ((Segment shr 16) + 1) shl 16;
Dec(ThisSize, $00010000);
end
else
begin
PFileData := Windows.MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0,
Segment, ThisSize);
if PFileData = nil then
begin
ReleaseMemory;
Exit;
end;
if not MoveDataTo(PFileData, PDest, ThisSize) then Exit;
Windows.UnmapViewOfFile(PFileData);
Dec(ThisSize, ThisSize);
end;
end;
PFileData := nil;
Result := True;
finally
if PFileData <> nil then Windows.UnmapViewOfFile(PFileData);
if MappingHandle <> 0 then Windows.CloseHandle(MappingHandle);
if FileHandle <> INVALID_HANDLE_VALUE then Windows.CloseHandle(FileHandle);
end;
except
on Exception do
begin
if PFileData <> nil then Windows.UnmapViewOfFile(PFileData);
if MappingHandle <> 0 then Windows.CloseHandle(MappingHandle);
if FileHandle <> INVALID_HANDLE_VALUE then Windows.CloseHandle(FileHandle);
ReleaseMemory;
Exit;
end
end;
end;