Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
stunndard committed Jun 20, 2024
0 parents commit 3a95cee
Show file tree
Hide file tree
Showing 12 changed files with 2,278 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.local
*.res
*.dres
*.identcache
__history/
__recovery/
Win32/
Win64/
20 changes: 20 additions & 0 deletions GoWin7Fixer.dpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
program GoWin7Fixer;

{$R *.dres}

uses
Vcl.Forms,
Main in 'Main.pas' {frmMain},
Patcher in 'Patcher.pas',
Vcl.Themes,
Vcl.Styles;

{$R *.res}

begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
TStyleManager.TrySetStyle('Windows10 SlateGray');
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end.
1,017 changes: 1,017 additions & 0 deletions GoWin7Fixer.dproj

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions GoWin7FixerResource.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dll32 RCDATA "acryptprimitives32.dll"
dll64 RCDATA "acryptprimitives64.dll"
Binary file added GoWin7Fixer_Icon.ico
Binary file not shown.
812 changes: 812 additions & 0 deletions Main.dfm

Large diffs are not rendered by default.

122 changes: 122 additions & 0 deletions Main.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
unit Main;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Imaging.jpeg,
ShellApi, Vcl.ExtCtrls;

type
TfrmMain = class(TForm)
txtLog: TMemo;
cmdOpen: TButton;
imgPic: TImage;
dlgOpen: TOpenDialog;
procedure imgPicClick(Sender: TObject);
procedure cmdOpenClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
procedure TryPatch(fileName: string);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmMain: TfrmMain;

implementation

{$R *.dfm}

uses
Patcher;

var
filesDropped: boolean = False;

function ChangeWindowMessageFilterEx(HWND: integer; Msg: Cardinal;
Action: Dword; pChangeFilterStruct: pointer): BOOL; stdcall; external 'user32.dll';

procedure TfrmMain.cmdOpenClick(Sender: TObject);
begin
if not dlgOpen.Execute then
Exit;
txtLog.Clear;
TryPatch(dlgOpen.fileName);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
DragAcceptFiles(frmMain.Handle, True);
// enable drag and drop files for an elevated process
ChangeWindowMessageFilterEx(frmMain.Handle, WM_DROPFILES, 1, nil);
ChangeWindowMessageFilterEx(frmMain.Handle, WM_COPYDATA, 1, nil);
ChangeWindowMessageFilterEx(frmMain.Handle, WM_COPYGLOBALDATA, 1, nil);
end;

procedure TfrmMain.imgPicClick(Sender: TObject);
begin
ShellExecute(Self.Handle, 'open', 'https://github.com/rolandshoemaker', nil,
nil, SW_SHOWNORMAL);
end;

procedure TfrmMain.TryPatch(fileName: string);
var
res: boolean;
begin
res := Patch(fileName);
txtLog.Lines.AddStrings(Patcher.Log);
txtLog.Lines.Add('');
if (not filesDropped) and res then
begin
DropDLLs;
filesDropped := True;
txtLog.Lines.AddStrings(Patcher.Log);
txtLog.Lines.Add('');
end;
end;

procedure TfrmMain.WMDropFiles(var Msg: TWMDropFiles);
var
DropH: HDROP; // drop handle
DroppedFileCount: integer; // number of files dropped
FileNameLength: integer; // length of a dropped file name
fileName: string; // a dropped file name
i: integer; // loops thru all dropped files
begin
txtLog.Clear;
inherited;
// Store drop handle from the message
DropH := Msg.Drop;
try
// Get count of files dropped
DroppedFileCount := DragQueryFile(DropH, $FFFFFFFF, nil, 0);
// Get name of each file dropped and process it
for i := 0 to Pred(DroppedFileCount) do
begin
// get length of file name
FileNameLength := DragQueryFile(DropH, I, nil, 0);
// create string large enough to store file
SetLength(fileName, FileNameLength);
// get the file name
DragQueryFile(DropH, I, PChar(fileName), FileNameLength + 1);
// process file
if LowerCase(ExtractFileExt(fileName)) <> '.exe' then
begin
txtLog.Lines.Add(ExtractFileName(fileName) + ' is not an .EXE file');
end
else
TryPatch(fileName);
end;
finally
DragFinish(DropH);
end;
// Note we handled the message
Msg.Result := 0;
end;

end.
190 changes: 190 additions & 0 deletions Patcher.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
unit Patcher;

interface

uses
WinApi.Windows, System.SysUtils, System.Classes, System.Hash;

function Patch(fileName: string): boolean;
function DropDLLs: boolean;

var
Log: TStringList;

implementation

function FileSize(const aFilename: String): Int64;
var
info: TWin32FileAttributeData;
begin
result := -1;
if not GetFileAttributesEx(PChar(aFilename), GetFileExInfoStandard, @info) then
exit;
Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;

function PatchMem(pattern, buf: PAnsiChar; patternlen, buflen: integer): boolean;
var
i: integer;
begin
Result := False;
for i := 0 to buflen - patternlen - 1 do
begin
if CompareMem(pattern, @buf[i], patternlen) then
begin
Log.Add('patching at: 0x' + i.ToHexString(8));
buf[i] := 'a';
Result := True;
end;
end;
end;

function WriteFromResource(resName, fileName: string): boolean;
var
rs: TResourceStream;
fs: TFileStream;
begin
Result := False;
rs := TResourceStream.Create(HInstance, resName, RT_RCDATA);
try
if FileExists(fileName) then
begin
if THashMD5.GetHashString(rs) = THashMD5.GetHashStringFromFile(fileName) then
begin
Log.Add(fileName + ' is correct version, no change required.');
Result := True;
exit;
end;
// update the file
if not DeleteFile(fileName) then
begin
Log.Add('file ' + fileName + ' cannot be deleted, probably in use, trying to rename...');
if not RenameFile(fileName, fileName.Substring(0, fileName.Length - 1) + '_') then
begin
Log.Add('cannot rename it to ' + fileName.Substring(0, fileName.Length - 1) + '. check if it''s opened my another program.');
exit;
end;
end;
end;

rs.Seek(0, soFromBeginning);
try
{$WARNINGS OFF}
fs := TFileStream.Create(fileName, fmCreate or fmShareDenyRead);
{$WARNINGS ON}
except
Log.Add('cannot create file for writing: ' + fileName);
exit;
end;
fs.CopyFrom(rs);
fs.Free;
Log.Add('file written ok: ' + fileName);

Result := True;
finally
rs.Free;
end;
end;

function DropDLLs: boolean;
var
wd: string;
size1, size2: int64;
os64: boolean;
begin
Result := False;
Log.Clear;
Log.Add('checking additional files...');

SetLength(wd, MAX_PATH);
GetWindowsDirectory(PChar(wd), MAX_PATH);
wd := string(pchar(wd));

size1 := FileSize(wd + '\System32\kernel32.dll');
size2 := FileSize(wd + '\Sysnative\kernel32.dll');
if size1 = -1 then
begin
Log.Add('cannot get system DLL size.');
exit;
end;

os64 := size2 > size1;
if not WriteFromResource('dll32', wd + '\System32\acryptprimitives.dll') then
exit;
if os64 then
if not WriteFromResource('dll64', wd + '\Sysnative\acryptprimitives.dll') then
exit;

Log.Add('additional files are ok.');
Result := True;
end;

function Patch(fileName: string): boolean;
var
fs, bs: TFileStream;
ms: TMemoryStream;
buf: PAnsiChar;
c1, c2: PAnsiChar;
begin
Result := False;
Log.Clear;
Log.Add('checking file: ' + ExtractFileName(fileName) + '...');
try
{$WARNINGS OFF}
fs := TFileStream.Create(fileName, fmOpenReadWrite or fmShareDenyRead);
{$WARNINGS ON}
GetMem(buf, fs.Size);
fs.Read(buf^, fs.Size);
except
Log.Add('couldn''t read the file, check if it''s opened by another program.');
exit;
end;

ms := TMemoryStream.Create;
ms.CopyFrom(fs);
ms.Seek(0, soFromBeginning);

try
c1 := 'bcryptprimitives.dll';
c2 := @string(c1)[1];
if not(PatchMem(c1, buf, Length(c1), fs.Size) and PatchMem(c2, buf,
Length(c1) * 2, fs.Size)) then
begin
Log.Add('couldn''t find the required data to patch. file not changed.');
exit;
end;

// write the changes
fs.Seek(0, soFromBeginning);
fs.Write(buf^, fs.Size);
Log.Add('saved ok.');

// save file backup
try
{$WARNINGS OFF}
bs := TFileStream.Create(fileName + '.bak', fmCreate or fmShareDenyRead);
{$WARNINGS ON}
except
Log.Add('couldn''t save backup file ' + fileName + '.bak');
exit;
end;
bs.CopyFrom(ms);
bs.Free;
Log.Add('backup saved ok.');
finally
fs.Free;
ms.Free;
end;
Result := True;
Log.Add('file successfully patched.');
end;

initialization

Log := TStringList.Create;

finalization

Log.Free;

end.
Loading

0 comments on commit 3a95cee

Please sign in to comment.