L1 := fs1.
L2 := fs2.
BytesRead1 :=F1.
BytesRead2 :=F2.
Взято с
unit findin;
interface
uses
Windows, SysUtils, findstr;
type
TFindInFile =
class;
TFindIn =
class
protected
FFindInFile: TFindInFile;
FHandle: THandle;
function GetPartNum: Integer;
virtual;
abstract;
function GetPartLen(
Index: Integer): Cardinal;
virtual;
abstract;
public
constructor Create(FindInFile: TFindInFile; FileName:
string);
virtual;
destructor Destroy;
override;
function CanUseMem: Boolean;
virtual;
abstract;
function UseMemSize: Cardinal;
virtual;
abstract;
function GetPart(
Index: Integer; Len: Cardinal): Pointer;
virtual;
abstract;
property PartNum: Integer
read GetPartNum;
property PartLen[
Index: Integer]: Cardinal
read GetPartLen;
end;
TFindInClass =
class of TFindIn;
TBMSearchFunc =
function(
var Buffer; BufLength: Cardinal;
var BT: TBMTbl;
MatchString: PAnsiChar;
var Pos: Cardinal): Boolean;
TFindInFile =
class
protected
FFindIn: TFindIn;
FFindInClass: TFindInClass;
FFindStrParams: PFindStrParams;
FMemHandle: THandle;
FMem: Pointer;
FStrLen: Cardinal;
FDriveTp: UINT;
FBMSearchFunc: TBMSearchFunc;
function GetDriveTp(Root:
string): UINT;
public
constructor Create(FindStrParams: PFindStrParams);
destructor Destroy;
override;
function Find(FileName:
string): Cardinal;
function SwitchToRoot(Root:
string): Boolean;
virtual;
end;
TFindInHDD =
class(TFindIn)
private
FSize: Cardinal;
protected
FMapPtr: Pointer;
function GetPartNum: Integer;
override;
function GetPartLen(
Index: Integer): Cardinal;
override;
public
constructor Create(FindInFile: TFindInFile; FileName:
string);
override;
destructor Destroy;
override;
function CanUseMem: Boolean;
override;
function UseMemSize: Cardinal;
override;
function GetPart(
Index: Integer; Len: Cardinal): Pointer;
override;
end;
PIntArr = ^TIntArr;
TIntArr =
array[0..1]
of Cardinal;
TFindInRemovable =
class(TFindIn)
private
FSize: Cardinal;
protected
FPartNum: Integer;
function GetPartNum: Integer;
override;
function GetPartLen(
Index: Integer): Cardinal;
override;
public
constructor Create(FindInFile: TFindInFile; FileName:
string);
override;
function CanUseMem: Boolean;
override;
function UseMemSize: Cardinal;
override;
function GetPart(
Index: Integer; Len: Cardinal): Pointer;
override;
end;
implementation
resourcestring
SInvalidDrive = 'Invalid drive - "%s".';
{ TFindIn }
constructor TFindIn.Create(FindInFile: TFindInFile; FileName:
string);
begin
inherited Create;
FFindInFile := FindInFile;
FHandle := CreateFile(PChar(FileName), GENERIC_
READ,
FILE_SHARE_
READ,
nil, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, 0);
if FHandle = INVALID_HANDLE_VALUE
then
RaiseLastWin32Error;
end;
destructor TFindIn.Destroy;
begin
if FHandle <> 0
then
CloseHandle(FHandle);
inherited Destroy;
end;
{ TFindInHDD }
constructor TFindInHDD.Create(FindInFile: TFindInFile; FileName:
string);
var
hFile: THandle;
begin
inherited Create(FindInFile, FileName);
FSize := GetFileSize(FHandle,
nil);
hFile := CreateFileMapping(FHandle,
nil, PAGE_
READONLY, 0, 0,
nil);
CloseHandle(FHandle);
FHandle := hFile;
if FHandle <> 0
then
begin
FMapPtr := MapViewOfFile(FHandle,
FILE_MAP_
READ, 0, 0, 0);
if FMapPtr =
nil then
RaiseLastWin32Error;
end
else
RaiseLastWin32Error;
end;
destructor TFindInHDD.Destroy;
begin
if FMapPtr <>
nil then
UnmapViewOfFile(FMapPtr);
inherited Destroy;
end;
function TFindInHDD.GetPartNum: Integer;
begin
Result := 1;
end;
function TFindInHDD.GetPartLen(
Index: Integer): Cardinal;
begin
Result := FSize;
end;
function TFindInHDD.GetPart(
Index: Integer; Len: Cardinal): Pointer;
begin
Result := FMapPtr;
end;
function TFindInHDD.CanUseMem: Boolean;
begin
Result := False;
end;
function TFindInHDD.UseMemSize: Cardinal;
begin
Result := 0;
end;
{ TFindInRemovable }
constructor TFindInRemovable.Create(FindInFile: TFindInFile; FileName:
string);
var
S: Cardinal;
begin
inherited Create(FindInFile, FileName);
FSize := GetFileSize(FHandle,
nil);
if FSize = $FFFFFFFF
then
RaiseLastWin32Error;
S := UseMemSize - Pred(FFindInFile.FStrLen);
FPartNum := FSize
div S;
if FSize
mod S <> 0
then
Inc(FPartNum);
end;
function TFindInRemovable.GetPartNum: Integer;
begin
Result := FPartNum;
end;
function TFindInRemovable.GetPartLen(
Index: Integer): Cardinal;
begin
Result := UseMemSize;
if (
Index = Pred(FPartNum))
and (FSize
mod (Result - FFindInFile.FStrLen) <> 0)
then
Result := FSize - (Result - Pred(FFindInFile.FStrLen)) * Pred(FPartNum);
end;
function TFindInRemovable.GetPart(
Index: Integer; Len: Cardinal): Pointer;
var
Dist: ULONG;
Reading: DWORD;
begin
Result := FFindInFile.FMem;
Dist :=
Index * (UseMemSize - Pred(FFindInFile.FStrLen));
SetFilePointer(FHandle, Dist,
nil,
FILE_
BEGIN);
if not ReadFile(FHandle, Result^, Len, Reading,
nil)
then
RaiseLastWin32Error;
end;
function TFindInRemovable.CanUseMem: Boolean;
begin
Result := True;
end;
function TFindInRemovable.UseMemSize: Cardinal;
begin
Result := 8; {512 * 1024;}
end;
{ TFindInFile }
function Max(V1, V2: Integer): Integer;
assembler;
register;
asm
CMP EAX,EDX
JG @@1
MOV EAX,EDX
@@1:
end;
constructor TFindInFile.Create(FindStrParams: PFindStrParams);
var
I: Integer;
begin
inherited Create;
FDriveTp := $FFFFFFFF;
FFindStrParams := FindStrParams;
if FFindStrParams^.CaseSensitive
then
FBMSearchFunc := BMSearch
else
FBMSearchFunc := BMSearchUC;
FStrLen := 0;
for I := 0
to Pred(FFindStrParams^.Substr.Count)
do
FStrLen := Max(FStrLen, length(FFindStrParams^.Substr[I]));
end;
destructor TFindInFile.Destroy;
begin
if FMemHandle <> 0
then
begin
GlobalUnlock(FMemHandle);
GlobalFree(FMemHandle);
end;
inherited Destroy;
end;
function TFindInFile.GetDriveTp(Root:
string): UINT;
begin
Result := GetDriveType(PChar(ExtractFileDrive(Root) + '\'));
end;
function TFindInFile.Find(FileName:
string): Cardinal;
var
I, J, K: Integer;
L: Cardinal;
P: Pointer;
PI: PFindStrInfo;
BMSFunc: TBMSFunc;
begin
Result := NotFound;
FFindIn := FFindInClass.Create(Self, FileName);
try
if FFindIn.CanUseMem
and (FMem =
nil)
then
begin
FMemHandle := GlobalAlloc(GMEM_MOVEABLE, FFindIn.UseMemSize);
if FMemHandle = 0
then
RaiseLastWin32Error;
FMem := GlobalLock(FMemHandle);
end;
for I := 0
to Pred(FFindIn.PartNum)
do
for J := 0
to Pred(FFindStrParams^.Substr.Count)
do
begin
L := FFindIn.PartLen[I];
P := FFindIn.GetPart(I, L);
Result := FindString(P^, L, J, FFindStrParams);
PI := PFindStrInfo(FFindStrParams.Substr.Objects[J]);
if FBMSearchFunc(P^, L, PI^.BMTbl, PI^.FindS, Result)
then
begin
if I > 0
then
for K := 1
to I - 1
do
Inc(Result, FFindIn.PartLen[K]);
Exit;
end;
end;
finally
FFindIn.Free;
end;
end;
function TFindInFile.SwitchToRoot(Root:
string): Boolean;
var
Tp: UINT;
begin
Tp := GetDriveTp(Root);
if Tp <> FDriveTp
then
case Tp
of
0, 1: Exception.CreateFmt(SInvalidDrive, [Root]);
DRIVE_FIXED: FFindInClass := TFindInHDD;
else
{DRIVE_REMOVABLE:
DRIVE_REMOTE:
DRIVE_CDROM:
DRIVE_RAMDISK:}
FFindInClass := TFindInRemovable;
end;
end;
end.