ReadFileToBuffer

    技术2022-05-20  59

    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;


    最新回复(0)