Delphi-Quellcode:
P1 := MapViewOfFile(MMF1.fFileMap, FILE_MAP_READ, CurPos, CurPos + AllocGran, AllocGran);
P2 := MapViewOfFile(MMF2.fFileMap, FILE_MAP_READ, CurPos, CurPos + AllocGran, AllocGran);
if not CompareMem(P1, P2, AllocGran) then Exit;
Inc(CurPos, AllocGran);
Ich sehe zwei Fehler
1.) MapViewOfFile() erwartet den Dateioffset der gemappt werden soll als 2x DWord. Du musst also CurPos als Int64 in zwei DWords zerlegen
2.) MapViewOfFile() kann fehlschlagen und dann ist P1 und/oder P2 = nil !
Nun, da du CurPos in MapViewOfFile() FALSCH übergibst ist sogar P1 und P2 = nil und daher deine
AV.
Richtiger so
Delphi-Quellcode:
var
CurPosHi,CurPosLo: DWord;
CurSize: DWord;
CurPos: Int64;
FileHandle1, FileHandle2: THandle;
MapHandle1, MapHandle2: THandle;
FileSize: Int64;
begin
Result := False;
FileHandle1 := CreateFile(..., FileName1, ...);
if FileHandle1 <> INVALID_HANDLE_VALUE then
try
FileHandle2 := CreateFile(..., FileName2, ...);
if FileHandle2 <> INVALID_HANDLE_VALUE then
try
FileSize := GetFileSizeInt64(FileHandle1);
if FileSize = GetFileSizeInt64(FileHandle1) then
begin
Result := True;
if FileSize1 > 0 then
begin
MapHandle1 := CraeteFileMapping(FileHandle1);
if MapHandle1 <> INVALID_HANDLE_VALUE then
try
MapHandle2 := CreateFileMapping(FileHandle2);
if MapHandle2 <> INVALID_HANDLE_VALUE then
try
CurSize := FileSize mod AllocGran;
if CurSize = 0 then CurSize := AllocGran;
CurPos := FileSize - CurSize;
repeat
CurPosHi := CurPos div 2^32;
CurPosLo := CurPos mod 2^32;
P1 := MapViewOfFile(MapHandle1, ..., CurPosHi, CurPosLo, CurSize);
if P1 <> nil then
try
P2 := MapViewOfFile(MapHandle2, ..., CurPosHi, CurPosLo, CurSize);
if P2 <> nil then
try
Result := CompareMem(P1, P2, CurSize);
finally
UnmapViewOfFile(P2);
end else RaiseLastWin32Error;
finally
UnmapViewOfFile(P1);
end else RaiseLastWin32Error;
CurPos := CurPos - CurSize;
CurSize := AllocGran;
until (CurPos < 0) or not Result;
finally
CloseFileMapping(MapHandle2);
end else RaiseLastWin32Error;
finally
CloseFileMapping(MapHandle1);
end else RaiseLastWin32Error;
end;
end;
finally
CloseFile(FileHandle2);
end else RaiseLastWin32Error;
finally
CloseFile(FileHand1e1);
end else RaiseLastWin32Error;
end;
Eventuelle Fehler in obigen Pseudocode darfst du behalten
Die Idee das Filemapping erst wirklich in der Vergleichs-Operation zu erzeugen halte ich für absolut richtig. Das wäre mein nächster Vorschlag gewesen. Alledings hätte ich sogar noch das CreateFileMapping() mit in die Vergleichsfunktion integriert.
Gruß hagen
Edit: shit nun zum 3. mal eine Änderung.
Code arbeitet die Datei nun von Hinten nach Vorne ab, da die Wahrscheinlichkeit das sich de dateien am Ende unterscheiden höher sein dürfte. Das Exit/Break wurde entfernt, so ist es sauberer. Try Finallys niemals vergessen !!