以前的代码:
program BinaryReplace;
uses
  Forms,
  BinRep1 in 'BinRep1.pas' {BinaryEdit};
{$R *.RES}
begin
  Application.Initialize;
  Application.CreateForm(TBinaryEdit, BinaryEdit);
  Application.Run;
end.
unit BinRep1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, ComCtrls, Buttons, ShellAPI;
CONST
  Max_Buffer = 4096;
type
  Buffer_Type = ARRAY [1..Max_Buffer] OF BYTE;
  TBinaryEdit = class(TForm)
    EXE_Name: TEdit;
    OpenDialog1: TOpenDialog;
    Label1: TLabel;
    Label4: TLabel;
    GroupBox1: TGroupBox;
    Label5: TLabel;
    orig_ico: TEdit;
    new_ico: TEdit;
    Label6: TLabel;
    GroupBox2: TGroupBox;
    Label2: TLabel;
    Find_Str: TEdit;
    Label3: TLabel;
    Replace_Str: TEdit;
    Zero_Breaks: TCheckBox;
    Progress: TProgressBar;
    Bevel1: TBevel;
    Browse2: TBitBtn;
    Browse3: TBitBtn;
    Browse: TBitBtn;
    Modify_Icon: TBitBtn;
    Modify_String: TBitBtn;
    First_Only: TCheckBox;
    Image1: TImage;
    Image2: TImage;
    Bevel2: TBevel;
    Bevel3: TBevel;
    Prev_Icon: TSpeedButton;
    Next_Icon: TSpeedButton;
    procedure Modify_StringClick(Sender: TObject);
    procedure BrowseClick(Sender: TObject);
    procedure Modify_IconClick(Sender: TObject);
    procedure Browse2Click(Sender: TObject);
    procedure Browse3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Extract_IconClick(Sender: TObject);
    procedure Next_IconClick(Sender: TObject);
    procedure Prev_IconClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    PROCEDURE Modify_File;
  end;
var
  BinaryEdit: TBinaryEdit;
  Data_In  : FILE OF BYTE;
  Data_Out : FILE OF BYTE;
  Find_Buffer : Buffer_Type;
  Rep_Buffer  : Buffer_Type;
  Find_Size   : INTEGER;
  Rep_Size    : INTEGER;
  Icon_Index  : INTEGER;
  Run_Path    : STRING;
implementation
{$R *.DFM}
procedure TBinaryEdit.Modify_StringClick(Sender: TObject);
VAR
  n : INTEGER;
BEGIN
  IF Zero_Breaks.Checked
  THEN
  BEGIN
    IF ((Length(Find_Str.Text) * 2 - 1) > Max_Buffer) OR ((Length(Replace_Str.Text) * 2 - 1) > Max_Buffer)
    THEN
    BEGIN
      MessageDlg('The text data is too large. Only data up to ' + IntToStr(Max_Buffer) + ' bytes can be replaced in a single modifcation',
                 mtWarning, [mbOk], 0);
      Exit;
    END;
  END
  ELSE
  BEGIN
    IF (Length(Find_Str.Text) > Max_Buffer) OR (Length(Replace_Str.Text) > Max_Buffer)
    THEN
    BEGIN
      MessageDlg('The text data is too large. Only data up to ' + IntToStr(Max_Buffer) + ' bytes can be replaced in a single modifcation',
                 mtWarning, [mbOk], 0);
      Exit;
    END;
  END;
  FOR n := 1 TO Length(Find_Str.Text)
  DO
    IF Zero_Breaks.Checked
    THEN
    BEGIN
      Find_Buffer[n * 2 - 1] := ORD(Find_Str.Text[n]);
      Find_Buffer[n * 2] := 0;
    END
    ELSE
      Find_Buffer[n] := ORD(Find_Str.Text[n]);
  IF Zero_Breaks.Checked
  THEN
    Find_Size := Length(Find_Str.Text) * 2 - 1
  ELSE
    Find_Size := Length(Find_Str.Text);
  IF Length(Replace_Str.Text) >= Length(Find_Str.Text)
  THEN
    Replace_Str.Text := Copy(Replace_Str.Text, 1, Length(Find_Str.Text));
  FOR n := 1 TO Length(Replace_Str.Text)
  DO
    IF Zero_Breaks.Checked
    THEN
    BEGIN
      Rep_Buffer[n * 2 - 1] := ORD(Replace_Str.Text[n]);
      Rep_Buffer[n * 2] := 0;
    END
    ELSE
      Rep_Buffer[n] := ORD(Replace_Str.Text[n]);
  IF Zero_Breaks.Checked
  THEN
    Rep_Size := Length(Replace_Str.Text) * 2 - 1
  ELSE
    Rep_Size := Length(Replace_Str.Text);
  IF Rep_Size < Find_Size
  THEN
    REPEAT
      Rep_Size := Rep_Size + 1;
      Rep_Buffer[Rep_Size] := 0;
    UNTIL Rep_Size = Find_Size;
  Modify_File;
END;
PROCEDURE TBinaryEdit.Modify_File;
VAR
  temp_byte     : BYTE;
  n             : INTEGER;
  Buffer        : Buffer_Type;
  Count         : INTEGER;
  Replaced      : INTEGER;
  Read_Count    : LONGINT;
  New_Ext       : STRING;
  Search_Active : BOOLEAN;
  Replace_First : BOOLEAN;
begin
{MessageDlg('Find Buffer: ' + IntToStr(Find_Size) + ' Rep Buffer: ' + IntToStr(Rep_Size), mtInformation, [mbOk], 0);}
  IF NOT(FileExists(EXE_Name.text))
  THEN
  BEGIN
    MessageDlg('Source file "' + orig_ico.text + '" not found', mtWarning, [mbOk], 0);
    Exit;
  END;
  New_Ext := ExtractFileExt(EXE_Name.Text); {Get old ext}
  IF New_Ext[1] = '.'                       {Strip off leading '.' (if there is one)}
  THEN
    New_Ext := Copy(New_Ext, 2, Length(New_Ext) - 1);
  New_Ext := '.~' + Copy(New_Ext, 1, Length(New_Ext) - 1); {Add the leading '~'}
  IF FileExists(ChangeFileExt(EXE_Name.Text, New_Ext)) {Do we have an existing backup?}
  THEN
    DeleteFile(ChangeFileExt(EXE_Name.Text, New_Ext)); {Delete it}
  RenameFile(EXE_Name.Text, ChangeFileExt(EXE_Name.Text, New_Ext)); {Create a new backup}
  AssignFile(data_in, ChangeFileExt(EXE_Name.Text, New_Ext));
  Reset(data_in);
  AssignFile(data_out, EXE_Name.Text);
  ReWrite(data_out);
  Screen.Cursor := crHourglass;
  Replaced := 0;
  Read_Count := 0;
  Progress.Max := FileSize(data_in) DIV 1024;
  Progress.Position := 0;
  Progress.Visible := TRUE;
  Search_Active := TRUE;
  Replace_First := First_Only.Checked;
  WHILE NOT(EOF(data_in))
  DO
  BEGIN
    READ(data_in, temp_byte);
    Read_Count := Read_Count + 1;
    IF (temp_byte = Find_Buffer[1]) AND Search_Active
    THEN                          {Does the read byte match the first byte in the buffer?}
    BEGIN                         {Yes. Check to see if the following bytes also match the buffer}
      Count := 1;
      Buffer[1] := Find_Buffer[1];
      WHILE NOT(EOF(data_in)) AND (count < Find_Size) AND (Buffer[count] = Find_Buffer[count])
      DO
      BEGIN
        count := count + 1;
        READ(data_in, Buffer[count]);
        Read_Count := Read_Count + 1;
      END;
      IF count = Find_Size        {Did what we read, match what we were looking for?}
      THEN
      BEGIN
        FOR n := 1 TO Count       {Yes. Output the replacement data}
        DO
          WRITE(data_out, Rep_Buffer[n]);
        Replaced := Replaced + 1;
        Search_Active := NOT(Replace_First);
      END
      ELSE
        FOR n := 1 TO Count       {No. Output wthe original data}
        DO
          WRITE(data_out, Buffer[n]);
    END
    ELSE
      WRITE(data_out, temp_byte);
    IF (Read_Count MOD 1024) = 0 {Have we read a K?}
    THEN
    BEGIN                        {Update the progress indicators}
      Label1.Caption := 'Read: ' + IntToStr(Read_Count DIV 1024) + ' KBytes';
      Progress.Position := Progress.Position + 1;
      Application.ProcessMessages;
    END;
  END;
  CloseFile(data_in);
  CloseFile(data_out);
  Progress.Position := Progress.Max;
  Application.ProcessMessages;
  Progress.Visible := FALSE;
  Label1.Caption := '';
  Screen.Cursor := crDefault;
  CASE Replaced OF
    0 : MessageDlg('Data could not be located. No changes have been made', mtWarning, [mbOk], 0);
    1 : MessageDlg('Replaced ' + IntToStr(Replaced) + ' instance of the data', mtInformation, [mbOk], 0);
  ELSE
    MessageDlg('Replaced ' + IntToStr(Replaced) + ' instances of the data', mtInformation, [mbOk], 0);
  END;
end;
procedure TBinaryEdit.BrowseClick(Sender: TObject);
begin
  OpenDialog1.Filter := 'Executable Files (*.exe)|*.exe|All Files (*.*)|*.*';
  OpenDialog1.Filename := EXE_Name.Text;
  OpenDialog1.FilterIndex := 0;
  IF OpenDialog1.Execute
  THEN
  BEGIN
    EXE_Name.Text := OpenDialog1.Filename;
    Icon_Index := 0;
    Orig_Ico.Text := '';
    Extract_IconClick(Self);
  END;
end;
procedure TBinaryEdit.Modify_IconClick(Sender: TObject);
VAR
  Temp_Byte : BYTE;
  n         : INTEGER;
begin
{We can treat an icon replace exactly the same as a text replace. Both are simply}
{streams of bytes, but in the case of icons, the bytes come in from a file rather}
{than have the user type in several hundred values. This routine merely rips the }
{data from the two icon files (original file (what to look for) and the new file }
{(what to replace it with)), sets up the two buffers, and gets the search process}
{kicked off}
  IF NOT(FileExists(orig_ico.text))
  THEN
  BEGIN
    MessageDlg('Icon file "' + orig_ico.text + '" not found', mtWarning, [mbOk], 0);
    Exit;
  END;
  IF NOT(FileExists(new_ico.text))
  THEN
  BEGIN
    MessageDlg('Icon file "' + new_ico.text + '" not found', mtWarning, [mbOk], 0);
    Exit;
  END;
  AssignFile(data_in, orig_ico.text);
  Reset(data_in);
  Find_Size := 0;
  FOR n := 1 TO 43
  DO
    READ(data_in, temp_byte); {Skip first 43 bytes (Header?)}
  WHILE NOT(EOF(data_in))
  DO
  BEGIN
    READ(data_in, temp_byte);
    Find_Size := Find_Size + 1;
    IF Find_Size <= Max_Buffer
    THEN
      Find_Buffer[Find_Size] := Temp_Byte;
  END;
  CloseFile(data_in);
  AssignFile(data_in, new_ico.text);
  Reset(data_in);
  Rep_Size := 0;
  FOR n := 1 TO 43
  DO
    READ(data_in, temp_byte); {Skip first 43 bytes (Header?)}
  WHILE NOT(EOF(data_in))
  DO
  BEGIN
    READ(data_in, temp_byte);
    Rep_Size := Rep_Size + 1;
    IF Rep_Size <= Max_Buffer
    THEN
      Rep_Buffer[Rep_Size] := Temp_Byte;
  END;
  CloseFile(data_in);
  IF Rep_Size <> Find_Size
  THEN
  BEGIN
    MessageDlg('The two icons are not the same size (' + IntToStr(Find_Size) + ' & ' + IntToStr(Rep_Size) + '). Unable to modify',
               mtWarning, [mbOk], 0);
    Exit;
  END;
  IF (Rep_Size > Max_Buffer) OR (Find_Size > Max_Buffer)
  THEN
    MessageDlg('The icon data is too large. Only data up to ' + IntToStr(Max_Buffer) + ' bytes can be replaced in a single modifcation',
               mtWarning, [mbOk], 0)
  ELSE
    Modify_File;
end;
procedure TBinaryEdit.Browse2Click(Sender: TObject);
begin
  OpenDialog1.Filter := 'Icon Files (*.ico)|*.ico|All Files (*.*)|*.*';
  OpenDialog1.Filename := Orig_Ico.Text;
  OpenDialog1.FilterIndex := 0;
  IF OpenDialog1.Execute
  THEN
  BEGIN
    Orig_Ico.Text := OpenDialog1.Filename;
    Image1.Picture.LoadFromFile(Orig_Ico.Text);
  END;
end;
procedure TBinaryEdit.Browse3Click(Sender: TObject);
begin
  OpenDialog1.Filter := 'Icon Files (*.ico)|*.ico|All Files (*.*)|*.*';
  OpenDialog1.Filename := New_Ico.Text;
  OpenDialog1.FilterIndex := 0;
  IF OpenDialog1.Execute
  THEN
  BEGIN
    New_Ico.Text := OpenDialog1.Filename;
    Image2.Picture.LoadFromFile(New_Ico.Text);
  END;
end;
procedure TBinaryEdit.FormCreate(Sender: TObject);
begin
  Run_Path := ExtractFilePath(ParamStr(0));
  IF Run_Path[Length(Run_Path)] <> '\'
  THEN
    Run_Path := Run_Path + '\';
  ClientWidth := Bevel1.Width;
  ClientHeight := Bevel1.Top + Bevel1.Height;
  Label1.Caption := '';
  Progress.Visible := FALSE;
  Application.Title := Caption;
end;
procedure TBinaryEdit.Extract_IconClick(Sender: TObject);
VAR
  icon_handle : LONGINT;
  buffer      : ARRAY [0..1024] OF CHAR;
begin
  IF NOT(FileExists(EXE_Name.Text))
  THEN
    Exit;
  StrPCopy(Buffer, EXE_Name.Text);
  icon_handle := ExtractIcon(BinaryEdit.Handle, buffer, icon_index);
  IF Icon_Handle = 0  {Did we get a valid handle back?}
  THEN
  BEGIN               {No}
    IF Icon_Index = 0 {Is this the first icon in the file?}
    THEN              {Yes. There can't be any icons in this file}
    BEGIN
      MessageDlg('No icons found in source file', mtWarning, [mbOk], 0);
      Image1.Visible := FALSE;
    END
    ELSE              {No. We must have gone beyond the limit. Step back}
      Icon_Index := Icon_Index - 1;
    Exit;
  END;
{We now have our extracted icon. Save it to a temp file in readiness for the modifocation}
  Image1.Picture.Icon.Handle := icon_handle;
  Image1.Picture.Icon.SaveToFile(Run_Path + 'orig.ico');
  orig_ico.Text := LowerCase(Run_Path + 'orig.ico');
  Image1.Visible := TRUE;
end;
procedure TBinaryEdit.Next_IconClick(Sender: TObject);
begin
  IF NOT(FileExists(EXE_Name.Text))
  THEN
    Exit;
  Icon_Index := Icon_Index + 1;
  Extract_IconClick(Self);
end;
procedure TBinaryEdit.Prev_IconClick(Sender: TObject);
begin
  IF NOT(FileExists(EXE_Name.Text)) OR (Icon_Index <= 0)
  THEN
    Exit;
  Icon_Index := Icon_Index - 1;
  Extract_IconClick(Self);
end;
end.