function ReadFileToBuffer(const AFileName: string; var AFileSize: Cardinal; var AData): Boolean;varFileHandle: 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;
beginResult := 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 thenbegin if not Windows.SetFileAttributes(PChar(AFileName), FileAttrs xor
FILE_ATTRIBUTE_READONLY) then Exit;end;
if ThisSize = 0 thenbegin 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; endend;end;