|
Reported by Doeke de Vries; checked by Jordan Russell
Jordan Russell:
Here is some code to reproduce the problem.
var
F: File;
begin
AssignFile(F, 'BigFile'); // a file larger than 2GB
Reset(F, 1000000);
Seek(F, 2148); // I/O error 131 here
CloseFile(F);
end;
This problem should be easy for Borland to fix. The Seek procedure does use a 64-bit multiply instruction to multiply the record number and record size together, but it discards the high-order 32 bits and passes NULL for the lpDistanceToMoveHigh parameter of the SetFilePointer call. This causes the error. In addition to properly passing the high-order 32 bits, it needs to use GetLastError for error checking since a FFFFFFFF result may not mean failure when a 64-bit offset is used.
Here's how I think the middle part of Delphi 6's _Seek procedure (in System.pas) should be written:
// SetFilePointer(f.Handle, recNum*f.RecSize, FILE_BEGIN
MOV EAX,[ECX].TFileRec.RecSize
MUL EDX
PUSH EDX
MOV EDX,ESP
PUSH FILE_BEGIN // pass dwMoveMethod
PUSH EDX // pass lpDistanceToMoveHigh
PUSH EAX // pass lDistanceToMove
PUSH [ECX].TFileRec.Handle // pass hFile
CALL SetFilePointer // get current position
POP EDX
INC EAX
JNZ @@exit
CALL GetLastError
TEST EAX,EAX
JZ @@exit
JMP InOutError
Note: The FilePos function also has a problem with >2GB offsets. |