Skip to content

Commit 3a95cee

Browse files
committed
Initial commit
0 parents  commit 3a95cee

12 files changed

+2278
-0
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.local
2+
*.res
3+
*.dres
4+
*.identcache
5+
__history/
6+
__recovery/
7+
Win32/
8+
Win64/

GoWin7Fixer.dpr

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
program GoWin7Fixer;
2+
3+
{$R *.dres}
4+
5+
uses
6+
Vcl.Forms,
7+
Main in 'Main.pas' {frmMain},
8+
Patcher in 'Patcher.pas',
9+
Vcl.Themes,
10+
Vcl.Styles;
11+
12+
{$R *.res}
13+
14+
begin
15+
Application.Initialize;
16+
Application.MainFormOnTaskbar := True;
17+
TStyleManager.TrySetStyle('Windows10 SlateGray');
18+
Application.CreateForm(TfrmMain, frmMain);
19+
Application.Run;
20+
end.

GoWin7Fixer.dproj

Lines changed: 1017 additions & 0 deletions
Large diffs are not rendered by default.

GoWin7FixerResource.rc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dll32 RCDATA "acryptprimitives32.dll"
2+
dll64 RCDATA "acryptprimitives64.dll"

GoWin7Fixer_Icon.ico

18.3 KB
Binary file not shown.

Main.dfm

Lines changed: 812 additions & 0 deletions
Large diffs are not rendered by default.

Main.pas

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
unit Main;
2+
3+
interface
4+
5+
uses
6+
Winapi.Windows, Winapi.Messages, System.SysUtils,
7+
System.Classes, Vcl.Graphics,
8+
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Imaging.jpeg,
9+
ShellApi, Vcl.ExtCtrls;
10+
11+
type
12+
TfrmMain = class(TForm)
13+
txtLog: TMemo;
14+
cmdOpen: TButton;
15+
imgPic: TImage;
16+
dlgOpen: TOpenDialog;
17+
procedure imgPicClick(Sender: TObject);
18+
procedure cmdOpenClick(Sender: TObject);
19+
procedure FormCreate(Sender: TObject);
20+
procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
21+
procedure TryPatch(fileName: string);
22+
private
23+
{ Private declarations }
24+
public
25+
{ Public declarations }
26+
end;
27+
28+
var
29+
frmMain: TfrmMain;
30+
31+
implementation
32+
33+
{$R *.dfm}
34+
35+
uses
36+
Patcher;
37+
38+
var
39+
filesDropped: boolean = False;
40+
41+
function ChangeWindowMessageFilterEx(HWND: integer; Msg: Cardinal;
42+
Action: Dword; pChangeFilterStruct: pointer): BOOL; stdcall; external 'user32.dll';
43+
44+
procedure TfrmMain.cmdOpenClick(Sender: TObject);
45+
begin
46+
if not dlgOpen.Execute then
47+
Exit;
48+
txtLog.Clear;
49+
TryPatch(dlgOpen.fileName);
50+
end;
51+
52+
procedure TfrmMain.FormCreate(Sender: TObject);
53+
begin
54+
DragAcceptFiles(frmMain.Handle, True);
55+
// enable drag and drop files for an elevated process
56+
ChangeWindowMessageFilterEx(frmMain.Handle, WM_DROPFILES, 1, nil);
57+
ChangeWindowMessageFilterEx(frmMain.Handle, WM_COPYDATA, 1, nil);
58+
ChangeWindowMessageFilterEx(frmMain.Handle, WM_COPYGLOBALDATA, 1, nil);
59+
end;
60+
61+
procedure TfrmMain.imgPicClick(Sender: TObject);
62+
begin
63+
ShellExecute(Self.Handle, 'open', 'https://github.com/rolandshoemaker', nil,
64+
nil, SW_SHOWNORMAL);
65+
end;
66+
67+
procedure TfrmMain.TryPatch(fileName: string);
68+
var
69+
res: boolean;
70+
begin
71+
res := Patch(fileName);
72+
txtLog.Lines.AddStrings(Patcher.Log);
73+
txtLog.Lines.Add('');
74+
if (not filesDropped) and res then
75+
begin
76+
DropDLLs;
77+
filesDropped := True;
78+
txtLog.Lines.AddStrings(Patcher.Log);
79+
txtLog.Lines.Add('');
80+
end;
81+
end;
82+
83+
procedure TfrmMain.WMDropFiles(var Msg: TWMDropFiles);
84+
var
85+
DropH: HDROP; // drop handle
86+
DroppedFileCount: integer; // number of files dropped
87+
FileNameLength: integer; // length of a dropped file name
88+
fileName: string; // a dropped file name
89+
i: integer; // loops thru all dropped files
90+
begin
91+
txtLog.Clear;
92+
inherited;
93+
// Store drop handle from the message
94+
DropH := Msg.Drop;
95+
try
96+
// Get count of files dropped
97+
DroppedFileCount := DragQueryFile(DropH, $FFFFFFFF, nil, 0);
98+
// Get name of each file dropped and process it
99+
for i := 0 to Pred(DroppedFileCount) do
100+
begin
101+
// get length of file name
102+
FileNameLength := DragQueryFile(DropH, I, nil, 0);
103+
// create string large enough to store file
104+
SetLength(fileName, FileNameLength);
105+
// get the file name
106+
DragQueryFile(DropH, I, PChar(fileName), FileNameLength + 1);
107+
// process file
108+
if LowerCase(ExtractFileExt(fileName)) <> '.exe' then
109+
begin
110+
txtLog.Lines.Add(ExtractFileName(fileName) + ' is not an .EXE file');
111+
end
112+
else
113+
TryPatch(fileName);
114+
end;
115+
finally
116+
DragFinish(DropH);
117+
end;
118+
// Note we handled the message
119+
Msg.Result := 0;
120+
end;
121+
122+
end.

Patcher.pas

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
unit Patcher;
2+
3+
interface
4+
5+
uses
6+
WinApi.Windows, System.SysUtils, System.Classes, System.Hash;
7+
8+
function Patch(fileName: string): boolean;
9+
function DropDLLs: boolean;
10+
11+
var
12+
Log: TStringList;
13+
14+
implementation
15+
16+
function FileSize(const aFilename: String): Int64;
17+
var
18+
info: TWin32FileAttributeData;
19+
begin
20+
result := -1;
21+
if not GetFileAttributesEx(PChar(aFilename), GetFileExInfoStandard, @info) then
22+
exit;
23+
Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
24+
end;
25+
26+
function PatchMem(pattern, buf: PAnsiChar; patternlen, buflen: integer): boolean;
27+
var
28+
i: integer;
29+
begin
30+
Result := False;
31+
for i := 0 to buflen - patternlen - 1 do
32+
begin
33+
if CompareMem(pattern, @buf[i], patternlen) then
34+
begin
35+
Log.Add('patching at: 0x' + i.ToHexString(8));
36+
buf[i] := 'a';
37+
Result := True;
38+
end;
39+
end;
40+
end;
41+
42+
function WriteFromResource(resName, fileName: string): boolean;
43+
var
44+
rs: TResourceStream;
45+
fs: TFileStream;
46+
begin
47+
Result := False;
48+
rs := TResourceStream.Create(HInstance, resName, RT_RCDATA);
49+
try
50+
if FileExists(fileName) then
51+
begin
52+
if THashMD5.GetHashString(rs) = THashMD5.GetHashStringFromFile(fileName) then
53+
begin
54+
Log.Add(fileName + ' is correct version, no change required.');
55+
Result := True;
56+
exit;
57+
end;
58+
// update the file
59+
if not DeleteFile(fileName) then
60+
begin
61+
Log.Add('file ' + fileName + ' cannot be deleted, probably in use, trying to rename...');
62+
if not RenameFile(fileName, fileName.Substring(0, fileName.Length - 1) + '_') then
63+
begin
64+
Log.Add('cannot rename it to ' + fileName.Substring(0, fileName.Length - 1) + '. check if it''s opened my another program.');
65+
exit;
66+
end;
67+
end;
68+
end;
69+
70+
rs.Seek(0, soFromBeginning);
71+
try
72+
{$WARNINGS OFF}
73+
fs := TFileStream.Create(fileName, fmCreate or fmShareDenyRead);
74+
{$WARNINGS ON}
75+
except
76+
Log.Add('cannot create file for writing: ' + fileName);
77+
exit;
78+
end;
79+
fs.CopyFrom(rs);
80+
fs.Free;
81+
Log.Add('file written ok: ' + fileName);
82+
83+
Result := True;
84+
finally
85+
rs.Free;
86+
end;
87+
end;
88+
89+
function DropDLLs: boolean;
90+
var
91+
wd: string;
92+
size1, size2: int64;
93+
os64: boolean;
94+
begin
95+
Result := False;
96+
Log.Clear;
97+
Log.Add('checking additional files...');
98+
99+
SetLength(wd, MAX_PATH);
100+
GetWindowsDirectory(PChar(wd), MAX_PATH);
101+
wd := string(pchar(wd));
102+
103+
size1 := FileSize(wd + '\System32\kernel32.dll');
104+
size2 := FileSize(wd + '\Sysnative\kernel32.dll');
105+
if size1 = -1 then
106+
begin
107+
Log.Add('cannot get system DLL size.');
108+
exit;
109+
end;
110+
111+
os64 := size2 > size1;
112+
if not WriteFromResource('dll32', wd + '\System32\acryptprimitives.dll') then
113+
exit;
114+
if os64 then
115+
if not WriteFromResource('dll64', wd + '\Sysnative\acryptprimitives.dll') then
116+
exit;
117+
118+
Log.Add('additional files are ok.');
119+
Result := True;
120+
end;
121+
122+
function Patch(fileName: string): boolean;
123+
var
124+
fs, bs: TFileStream;
125+
ms: TMemoryStream;
126+
buf: PAnsiChar;
127+
c1, c2: PAnsiChar;
128+
begin
129+
Result := False;
130+
Log.Clear;
131+
Log.Add('checking file: ' + ExtractFileName(fileName) + '...');
132+
try
133+
{$WARNINGS OFF}
134+
fs := TFileStream.Create(fileName, fmOpenReadWrite or fmShareDenyRead);
135+
{$WARNINGS ON}
136+
GetMem(buf, fs.Size);
137+
fs.Read(buf^, fs.Size);
138+
except
139+
Log.Add('couldn''t read the file, check if it''s opened by another program.');
140+
exit;
141+
end;
142+
143+
ms := TMemoryStream.Create;
144+
ms.CopyFrom(fs);
145+
ms.Seek(0, soFromBeginning);
146+
147+
try
148+
c1 := 'bcryptprimitives.dll';
149+
c2 := @string(c1)[1];
150+
if not(PatchMem(c1, buf, Length(c1), fs.Size) and PatchMem(c2, buf,
151+
Length(c1) * 2, fs.Size)) then
152+
begin
153+
Log.Add('couldn''t find the required data to patch. file not changed.');
154+
exit;
155+
end;
156+
157+
// write the changes
158+
fs.Seek(0, soFromBeginning);
159+
fs.Write(buf^, fs.Size);
160+
Log.Add('saved ok.');
161+
162+
// save file backup
163+
try
164+
{$WARNINGS OFF}
165+
bs := TFileStream.Create(fileName + '.bak', fmCreate or fmShareDenyRead);
166+
{$WARNINGS ON}
167+
except
168+
Log.Add('couldn''t save backup file ' + fileName + '.bak');
169+
exit;
170+
end;
171+
bs.CopyFrom(ms);
172+
bs.Free;
173+
Log.Add('backup saved ok.');
174+
finally
175+
fs.Free;
176+
ms.Free;
177+
end;
178+
Result := True;
179+
Log.Add('file successfully patched.');
180+
end;
181+
182+
initialization
183+
184+
Log := TStringList.Create;
185+
186+
finalization
187+
188+
Log.Free;
189+
190+
end.

0 commit comments

Comments
 (0)