- Incremento de versión a 1.6.5 git-svn-id: https://192.168.0.254/svn/Proyectos.Tecsitel_FactuGES2/trunk@866 0c75b7a4-871f-7646-8a2f-f78d34cc349f
421 lines
14 KiB
ObjectPascal
421 lines
14 KiB
ObjectPascal
{$A+,B-,C+,D+,E-,F-,G+,H+,I+,J+,K-,L+,M-,N+,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ MidasSpeedFix unit - Unoffical speed fix for Midas (Delphi/C++Builder 6 to 2009) }
|
|
{ Version 1.0 (2009-01-21) }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
|
|
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
|
|
{ License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
|
|
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
|
|
{ and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is MidasSpeedFix.pas. }
|
|
{ }
|
|
{ The Initial Developer of the Original Code is Andreas Hausladen (Andreas.Hausladen@gmx.de). }
|
|
{ Portions created by Andreas Hausladen are Copyright (C) 2009 Andreas Hausladen. }
|
|
{ All Rights Reserved. }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
|
|
{ History:
|
|
2009-01-21:
|
|
Initial implementation
|
|
|
|
How to use:
|
|
Add the MidasSpeedFix.pas unit to your Delphi or C++ Project (ProjectManager: Add Unit)
|
|
}
|
|
|
|
unit MidasSpeedFix;
|
|
|
|
interface
|
|
|
|
{$IFDEF CONDITIONALEXPRESSIONS}
|
|
{$IF CompilerVersion >= 15.0}
|
|
{$WARN UNSAFE_TYPE OFF}
|
|
{$WARN UNSAFE_CODE OFF}
|
|
{$WARN UNSAFE_CAST OFF}
|
|
{$IFEND}
|
|
{$ENDIF}
|
|
|
|
implementation
|
|
|
|
uses
|
|
Windows, SysUtils, DSIntf;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
|
|
function MidasMalloc(Size: LongWord): Pointer; stdcall;
|
|
begin
|
|
GetMem(Result, Size);
|
|
end;
|
|
|
|
procedure MidasFree(P: Pointer); stdcall;
|
|
begin
|
|
FreeMem(P);
|
|
end;
|
|
|
|
function MidasCalloc(Count, ElementSize: LongWord): Pointer; stdcall;
|
|
begin
|
|
Result := AllocMem(Count * ElementSize);
|
|
end;
|
|
|
|
function MidasRealloc(P: Pointer; OldSize, NewSize: LongWord): Pointer; stdcall;
|
|
begin
|
|
ReallocMem(P, NewSize);
|
|
Result := P;
|
|
if (Result <> nil) and (OldSize < NewSize) then
|
|
FillChar(Pointer(PAnsiChar(Result) + OldSize)^, NewSize - OldSize, 0);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
|
|
{$UNDEF REQUIRE_NEW_MEMORY_MANAGER}
|
|
|
|
{$IFDEF CONDITIONALEXPRESSIONS}
|
|
{$IF CompilerVersion < 18.0} // Delphi 2006 was the first shipped with FastMM
|
|
{$DEFINE REQUIRE_NEW_MEMORY_MANAGER}
|
|
{$IFEND}
|
|
{$ELSE}
|
|
{$DEFINE REQUIRE_NEW_MEMORY_MANAGER}
|
|
{$ENDIF CONDITIONALEXPRESSIONS}
|
|
|
|
type
|
|
TJumpOfs = Integer;
|
|
PPointer = ^Pointer;
|
|
|
|
type
|
|
PXRedirCode = ^TXRedirCode;
|
|
TXRedirCode = packed record
|
|
Jump: Byte;
|
|
Offset: TJumpOfs;
|
|
end;
|
|
|
|
{ Hooking }
|
|
|
|
procedure HookProc(Proc, Dest: Pointer; var BackupCode: TXRedirCode);
|
|
var
|
|
n: DWORD;
|
|
Code: TXRedirCode;
|
|
begin
|
|
Assert(Proc <> nil);
|
|
if ReadProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n) then
|
|
begin
|
|
Code.Jump := $E9;
|
|
Code.Offset := PAnsiChar(Dest) - PAnsiChar(Proc) - SizeOf(Code);
|
|
WriteProcessMemory(GetCurrentProcess, Proc, @Code, SizeOf(Code), n);
|
|
end;
|
|
end;
|
|
|
|
procedure UnhookProc(Proc: Pointer; var BackupCode: TXRedirCode);
|
|
var
|
|
n: Cardinal;
|
|
begin
|
|
if (BackupCode.Jump <> 0) and (Proc <> nil) then
|
|
begin
|
|
WriteProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n);
|
|
BackupCode.Jump := 0;
|
|
end;
|
|
end;
|
|
|
|
function FindMethodPtr(Start: THandle; const Bytes: array of Smallint): Pointer;
|
|
var
|
|
P, Address, BytePtr: PAnsiChar;
|
|
MemInfo: TMemoryBasicInformation;
|
|
I: Cardinal;
|
|
FirstByte: Byte;
|
|
StartOffset, Index: Integer;
|
|
BytesLen: Integer;
|
|
Found: Boolean;
|
|
AllocBase: Pointer;
|
|
begin
|
|
Result := nil;
|
|
BytesLen := Length(Bytes);
|
|
if (Start <> 0) and (BytesLen >= 8) then
|
|
begin
|
|
StartOffset := 0;
|
|
while (StartOffset < BytesLen) and (Bytes[StartOffset] = -1) do
|
|
Inc(StartOffset);
|
|
if StartOffset = BytesLen then
|
|
Exit;
|
|
FirstByte := Byte(Bytes[StartOffset]);
|
|
|
|
try
|
|
Address := PAnsiChar(Start);
|
|
if not VirtualQuery(Address, MemInfo, SizeOf(MemInfo)) = SizeOf(MemInfo) then
|
|
Exit;
|
|
AllocBase := MemInfo.AllocationBase;
|
|
|
|
while (VirtualQuery(Address, MemInfo, SizeOf(MemInfo)) = SizeOf(MemInfo)) and
|
|
(MemInfo.AllocationBase = AllocBase) do
|
|
begin
|
|
if MemInfo.Protect and $000000F0 <> 0 then // PAGE_EXECUTE | ...
|
|
begin
|
|
P := Address;
|
|
for I := 0 to MemInfo.RegionSize - 1 do
|
|
begin
|
|
if Byte(P[0]) = FirstByte then
|
|
begin
|
|
BytePtr := P + 1;
|
|
Found := True;
|
|
for Index := StartOffset + 1 to BytesLen - 1 do
|
|
begin
|
|
if (Bytes[Index] <> -1) and (Byte(Bytes[Index]) <> Byte(BytePtr^)) then
|
|
begin
|
|
Found := False;
|
|
Break;
|
|
end;
|
|
Inc(BytePtr);
|
|
end;
|
|
if Found then
|
|
begin
|
|
Result := P;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Inc(P);
|
|
end;
|
|
end;
|
|
Inc(Address, MemInfo.RegionSize);
|
|
end;
|
|
except
|
|
on E: EAccessViolation do
|
|
;
|
|
on E: EPrivilege do
|
|
;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
const
|
|
MidasMallocBytes: array[0..15] of SmallInt = (
|
|
$55, // push ebp
|
|
$8B, $EC, // mov ebp,esp
|
|
$FF, $75, $08, // push dword ptr [ebp+$08]
|
|
$E8, -1, -1, -1, -1, // call _malloc
|
|
$59, // pop ecx
|
|
$5D, // pop ebp
|
|
$C2, $04, $00 // ret $0004
|
|
);
|
|
|
|
MidasFreeBytes: array[0..20] of SmallInt = (
|
|
$55, // push ebp
|
|
$8B, $EC, // mov ebp,esp
|
|
$8B, $45, $08, // mov eax,[ebp+$08]
|
|
$85, $C0, // test eax,eax
|
|
$74, $07, // jz +$07
|
|
$50, // push eax
|
|
$E8, -1, -1, -1, -1, // call _free
|
|
$59, // pop ecx
|
|
$5D, // pop ebp
|
|
$C2, $04, $00 // ret $0004
|
|
);
|
|
|
|
MidasMallocBytesGlobal: array[0..56] of SmallInt = (
|
|
$55, // push ebp
|
|
$8B, $EC, // mov ebp,esp
|
|
$53, // push ebx
|
|
$56, // push esi
|
|
$57, // push edi
|
|
$33, $DB, // xor ebx, ebx
|
|
$66, $BE, $02, $00, // mov si, $0002
|
|
$FF, $75, $08, // push dword ptr [ebp+$08]
|
|
$0F, $BF, $C6, // movsx eax,si
|
|
$50, // push eax
|
|
$E8, -1, -1, -1, -1, // call GlobalAlloc
|
|
$8B, $F8, // mov edi,eax
|
|
$85, $C0, // test eax,eax
|
|
$74, $12, // jz +$12
|
|
$57, // push edi
|
|
$E8, -1, -1, -1, -1, // call GlobalLock
|
|
$8B, $D8, // mov ebx,eax
|
|
$85, $C0, // test eax,eax
|
|
$75, $06, // jnz +$06
|
|
$57, // push edi
|
|
$E8, -1, -1, -1, -1, // call GlobalFree
|
|
$8B, $C3, // mov eax,ebx
|
|
$5F, // pop edi
|
|
$5E, // pop esi
|
|
$5B, // pop ebx
|
|
$5D, // pop ebp
|
|
$C2, $04, $00 // ret $0004
|
|
);
|
|
|
|
MidasFreeBytesGlobal: array[0..39] of SmallInt = (
|
|
$55, // push ebp
|
|
$8B, $EC, // mov ebp,esp
|
|
$53, // push ebx
|
|
$8B, $45, $08, // mov eax,[ebp+$08]
|
|
$85, $C0, // test eax,eax
|
|
$74, $18, // jz +$18
|
|
$50, // push eax
|
|
$E8, -1, -1, -1, -1, // call GlobalHandle
|
|
$8B, $D8, // mov ebx,eax
|
|
$85, $DB, // test ebx,ebx
|
|
$74, $0C, // jz +$0c
|
|
$53, // puch ebx
|
|
$E8, -1, -1, -1, -1, // call GlobalUnlock
|
|
$53, // push ebx
|
|
$E8, -1, -1, -1, -1, // call GlobalFree
|
|
$5B, // pop ebx
|
|
$5D, // pop ebp
|
|
$C2, $04, $00 // ret $0004
|
|
);
|
|
|
|
MidasCallocBytes: array[0..43] of SmallInt = (
|
|
$55, // push ebp
|
|
$8B, $EC, // mov ebp,esp
|
|
$53, // push ebx
|
|
$56, // push esi
|
|
$8B, $75, $08, // mov esi,[ebp+$08]
|
|
$0F, $AF, $75, $0C, // imul esi,[ebp+$0c]
|
|
$56, // push esi
|
|
$E8, -1, -1, -1, -1, // call $004d2097 MidasMalloc
|
|
$8B, $D8, // mov ebx,eax
|
|
$85, $DB, // test ebx,ebx
|
|
$74, $0C, // jz +$0c
|
|
$56, // push esi
|
|
$6A, $00, // push $00
|
|
$53, // push ebx
|
|
$E8, -1, -1, -1, -1, // call _memset
|
|
$83, $C4, $0C, // add esp,$0c
|
|
$8B, $C3, // mov eax,ebx
|
|
$5E, // pop esi
|
|
$5B, // pop ebx
|
|
$5D, // pop ebp
|
|
$C2, $08, $00 // ret $0008
|
|
);
|
|
|
|
MidasReallocBytes: array[0..54] of SmallInt = (
|
|
$55, // push ebp
|
|
$8B, $EC, // mov ebp,esp
|
|
$53, // push ebx
|
|
$56, // push esi
|
|
$8B, $75, $08, // mov esi,[ebp+$08]
|
|
$FF, $75, $10, // push dword ptr [ebp+$10]
|
|
$6A, $01, // push $01
|
|
$E8, -1, -1, -1, -1, // call $004d20a7 MidasCalloc
|
|
$8B, $D8, // mov ebx,eax
|
|
$85, $DB, // test ebx,ebx
|
|
$74, $17, // jz +$17
|
|
$85, $F6, // test esi,esi
|
|
$74, $13, // jz +$13
|
|
$FF, $75, $0C, // push dword ptr [ebp+$0c]
|
|
$56, // push esi
|
|
$53, // push ebx
|
|
$E8, -1, -1, -1, -1, // call _memmove
|
|
$83, $C4, $0C, // add esp,$0c
|
|
$56, // push esi
|
|
$E8, -1, -1, -1, -1, // call $004d20d3 MidasFree
|
|
$8B, $C3, // mov eax,ebx
|
|
$5E, // pop esi
|
|
$5B, // pop ebx
|
|
$5D, // pop ebp
|
|
$C2, $0C, $00 // ret $000c
|
|
);
|
|
|
|
var
|
|
Org_MidasMalloc: Pointer;
|
|
Org_MidasFree: Pointer;
|
|
Org_MidasCalloc: Pointer;
|
|
Org_MidasRealloc: Pointer;
|
|
|
|
MidasMallocHook: TXRedirCode;
|
|
MidasFreeHook: TXRedirCode;
|
|
MidasCallocHook: TXRedirCode;
|
|
MidasReallocHook: TXRedirCode;
|
|
|
|
{$IFDEF REQUIRE_NEW_MEMORY_MANAGER}
|
|
function RequireNewerMemoryManager: Boolean;
|
|
var
|
|
MemMan: TMemoryManager;
|
|
begin
|
|
GetMemoryManager(MemMan);
|
|
if @MemMan.GetMem = @SysGetMem then
|
|
begin
|
|
MessageBox(0, 'You must install an alternative memory manager like FastMM4. FastMM4 must run in RELEASE mode to see an improved performance.',
|
|
'Delphi - Midas Speed Fix', MB_OK or MB_ICONERROR);
|
|
Result := False;
|
|
end
|
|
else
|
|
Result := True;
|
|
end;
|
|
{$ENDIF REQUIRE_NEW_MEMORY_MANAGER}
|
|
|
|
procedure Init;
|
|
var
|
|
DSBase: IDSBase;
|
|
IsCRTLMemMan: Boolean;
|
|
begin
|
|
{$IFDEF REQUIRE_NEW_MEMORY_MANAGER}
|
|
if not RequireNewerMemoryManager then
|
|
Exit;
|
|
{$ENDIF REQUIRE_NEW_MEMORY_MANAGER}
|
|
|
|
IsCRTLMemMan := True; // C RTL memory manager
|
|
Org_MidasMalloc := FindMethodPtr(HInstance, MidasMallocBytes);
|
|
if Org_MidasMalloc = nil then
|
|
begin
|
|
Org_MidasMalloc := FindMethodPtr(HInstance, MidasMallocBytesGlobal);
|
|
if Org_MidasMalloc <> nil then
|
|
IsCRTLMemMan := False;
|
|
end;
|
|
|
|
if Org_MidasMalloc = nil then
|
|
begin
|
|
CreateDbClientObject(CLSID_DSBase, IDSBase, DSBase); // load midas.dll
|
|
DSBase := nil; // release alloctated midas memory
|
|
|
|
Org_MidasMalloc := FindMethodPtr(GetModuleHandle('midas.dll'), MidasMallocBytes);
|
|
if Org_MidasMalloc = nil then
|
|
begin
|
|
Org_MidasMalloc := FindMethodPtr(HInstance, MidasMallocBytesGlobal);
|
|
if Org_MidasMalloc <> nil then
|
|
IsCRTLMemMan := False;
|
|
end;
|
|
end;
|
|
|
|
if Org_MidasMalloc = nil then
|
|
begin
|
|
OutputDebugString('Midas speed fix could not be installed.');
|
|
Exit;
|
|
end;
|
|
Assert(Org_MidasMalloc <> nil);
|
|
|
|
if IsCRTLMemMan then
|
|
Org_MidasFree := FindMethodPtr(HINST(Org_MidasMalloc), MidasFreeBytes)
|
|
else
|
|
Org_MidasFree := FindMethodPtr(HINST(Org_MidasMalloc), MidasFreeBytesGlobal);
|
|
|
|
Org_MidasCalloc := FindMethodPtr(HINST(Org_MidasMalloc), MidasCallocBytes);
|
|
Org_MidasRealloc := FindMethodPtr(HINST(Org_MidasMalloc), MidasReallocBytes);
|
|
|
|
Assert(Org_MidasFree <> nil);
|
|
Assert(Org_MidasCalloc <> nil);
|
|
Assert(Org_MidasRealloc <> nil);
|
|
|
|
HookProc(Org_MidasMalloc, @MidasMalloc, MidasMallocHook);
|
|
HookProc(Org_MidasFree, @MidasFree, MidasFreeHook);
|
|
HookProc(Org_MidasCalloc, @MidasCalloc, MidasCallocHook);
|
|
HookProc(Org_MidasRealloc, @MidasRealloc, MidasReallocHook);
|
|
end;
|
|
|
|
procedure Fini;
|
|
begin
|
|
UnhookProc(Org_MidasMalloc, MidasMallocHook);
|
|
UnhookProc(Org_MidasFree, MidasFreeHook);
|
|
UnhookProc(Org_MidasCalloc, MidasCallocHook);
|
|
UnhookProc(Org_MidasRealloc, MidasReallocHook);
|
|
end;
|
|
|
|
initialization
|
|
Init;
|
|
|
|
finalization
|
|
Fini;
|
|
|
|
end.
|