http://bbs.2ccc.com/topic.asp?topicid=617767
方法1 https://github.com/delphilite/DelphiHookUtils/blob/master/Demos/XP/XPCmpatibilityTweak.pas
var
GetTickCount64Next: function : UInt64; stdcall;
function GetTickCount64CallBack: UInt64; stdcall;
begin
if TOSVersion.Major < 6 then
Result := Winapi.Windows.GetTickCount
else Result := GetTickCount64Next;
end;
initialization
if TOSVersion.Major < 6 then
begin
HookProc(@Winapi.Windows.GetTickCount64, @GetTickCount64CallBack, @GetTickCount64Next);
end;
finalization
if Assigned(@GetTickCount64Next) then
begin
UnHookProc(@GetTickCount64Next);
end;
把
HookProc(@Winapi.Windows.GetTickCount64, @GetTickCount64CallBack, @GetTickCount64Next);
改成
HookProc('kernel32.dll','GetTickCount64', @GetTickCount64CallBack, @GetTickCount64Next);
就可以了。
第一种写法如果函数是Delphi实现的没问题,但是你这个是钩的导入表的跳转函数。
第二种写法是钩的kernel32.dll中函数的本体
另外如果要真实模拟你也可以在XP上自己实现一个64位的GetTickCount,可能比直接返回一个32位GetTickCount的精度要高一点点。
//----------------------------------------------------------------------------------------------------------------- http://bbs.2ccc.com/topic.asp?topicid=617636
| 26楼 | 男 2cc (2cc) |
var GetTickCount64Next: function : UInt64; stdcall = nil;
function HookDelphiIAT(HookAddr,FuncAddr:Pointer):Pointer;
begin
{\(IFDEF X32}
Result:=Pointer(PDWORD(PDWORD(DWORD(HookAddr)+2)^)^);
PDWORD(PDWORD(DWORD(HookAddr)+2)^)^:=DWORD(FuncAddr);
{\)ELSE}
Result:=Pointer(PDWORD64(PDWORD(DWORD(HookAddr)+2)^ + DWORD(HookAddr) + 6)^);
PDWORD64(PDWORD(DWORD(HookAddr)+2)^ + DWORD(HookAddr) + 6)^:= DWORD64(FuncAddr);
{$ENDIF}
end;
function GetTickCount64CallBack: UInt64; stdcall;
begin
if TOSVersion.Major < 6 then
Result := Winapi.Windows.GetTickCount
else Result := GetTickCount64Next;
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Winapi.Windows.GetTickCount64();
if @GetTickCount64Next = nil then
begin
GetTickCount64Next:=HookDelphiIAT(@Winapi.Windows.GetTickCount64,@GetTickCount64CallBack);
end;
Winapi.Windows.GetTickCount64();
ShowMessage('1111111111');
end;
wr960204 | 武稀松 | http://www.raysoftware.cn/40.html
一个可以再WIN2000及以上操作系统使用的GetTickCount64
发表于2012年9月12日由raysoftware
转自我的旧博客
以后尽量用Delphi/C++双代码写.
GetTickCount返回值是整数,这样的话最多49天多就会复位重新从0开始.Vista以后提供了GetTickCount64这个函数, 但是WindowsXP还是主流.在项目中为了处理这个,自己实现了一套办法.这个GetTickCount和真正的额GetTickCount相比会恒 定的相差800毫秒左右.不过这个不影响使用.获取开机时间这800毫秒完全可以忽略.计算时间差的话就和GetTickCount是一样的了.
Delphi版XE下编译通过.
type
_SYSTEM_INFORMATION_CLASS = (
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemNotImplemented1,
SystemProcessesAndThreadsInformation,
SystemCallCounts,
SystemConfigurationInformation,
SystemProcessorTimes,
SystemGlobalFlag,
SystemNotImplemented2,
SystemModuleInformation,
SystemLockInformation,
SystemNotImplemented3,
SystemNotImplemented4,
SystemNotImplemented5,
SystemHandleInformation,
SystemObjectInformation,
SystemPagefileInformation,
SystemInstructionEmulationCounts,
SystemInvalidInfoClass1,
SystemCacheInformation,
SystemPoolTagInformation,
SystemProcessorStatistics,
SystemDpcInformation,
SystemNotImplemented6,
SystemLoadImage,
SystemUnloadImage,
SystemTimeAdjustment,
SystemNotImplemented7,
SystemNotImplemented8,
SystemNotImplemented9,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemLoadAndCallImage,
SystemPrioritySeparation,
SystemNotImplemented10,
SystemNotImplemented11,
SystemInvalidInfoClass2,
SystemInvalidInfoClass3,
SystemTimeZoneInformation,
SystemLookasideInformation,
SystemSetTimeSlipEvent,
SystemCreateSession,
SystemDeleteSession,
SystemInvalidInfoClass4,
SystemRangeStartInformation,
SystemVerifierInformation,
SystemAddVerifier,
SystemSessionProcessesInformation);
SYSTEM_INFORMATION_CLASS = _SYSTEM_INFORMATION_CLASS;
TSystemInformationClass = SYSTEM_INFORMATION_CLASS;
_SYSTEM_TIME_OF_DAY_INFORMATION = record // Information Class 3
BootTime: LARGE_INTEGER;
CurrentTime: LARGE_INTEGER;
TimeZoneBias: LARGE_INTEGER;
CurrentTimeZoneId: ULONG;
end;
SYSTEM_TIME_OF_DAY_INFORMATION = _SYSTEM_TIME_OF_DAY_INFORMATION;
PSYSTEM_TIME_OF_DAY_INFORMATION = ^SYSTEM_TIME_OF_DAY_INFORMATION;
function? NtQuerySystemInformation(
SystemInformationClass : SYSTEM_INFORMATION_CLASS;
SystemInformation : PVOID;
SystemInformationLength : ULONG;
ReturnLength : PULONG
): Integer; stdcall; external ‘ntdll.dll’;
function? NtQuerySystemTime(
var CurrentTime : LARGE_INTEGER
): Integer; stdcall; external ‘ntdll.dll’;
function _GetTickCount64():Int64;
var
st : SYSTEM_TIME_OF_DAY_INFORMATION;
r : ULONG;
ct : LARGE_INTEGER;
begin
NtQuerySystemInformation(SystemTimeOfDayInformation,
@st,
SizeOf(SYSTEM_TIME_OF_DAY_INFORMATION),
@r);
NtQuerySystemTime(ct);
Result :=(ct.QuadPart-st.BootTime.QuadPart)div 10000;
end;
VC版:
typedef ULONGLONG (WINAPI GetTickCount64Proc)(void);
typedef ULONG (__stdcall * NTQUERYSYSTEMINFORMATION)(IN???? /SYSTEM_INFORMATION_CLASS/int, IN OUT PVOID, INT??? ULONG, OUT??? PULONG OPTION);
GetTickCount64Proc* VistaGetTickCount64 = (GetTickCount64Proc*)GetProcAddress(GetModuleHandle(_T(“kernel32.dll”)), “GetTickCount64”);
NTQUERYSYSTEMINFORMATION _NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle(_T(“ntdll.dll”)), (“NtQuerySystemInformation”));
INT64 _GetTickCount64()
{
typedef struct _SYSTEM_TIME_OF_DAY_INFORMATION
{
LARGE_INTEGER BootTime;
LARGE_INTEGER CurrentTime;
LARGE_INTEGER TimeZoneBias;
ULONG CurrentTimeZoneId;
} SYSTEM_TIME_OF_DAY_INFORMATION, *PSYSTEM_TIME_OF_DAY_INFORMATION;
//如果系统存在VistaGetTickCount64函数则调用系统的
if (VistaGetTickCount64)
return VistaGetTickCount64();
SYSTEM_TIME_OF_DAY_INFORMATION? st ={0};
ULONG?????????????????????????? oSize = 0;
if((NULL == _NtQuerySystemInformation)||0 !=(_NtQuerySystemInformation(3, &st, sizeof(st), &oSize))||
(oSize!= sizeof(st)))
return GetTickCount();
return (st.CurrentTime.QuadPart – st.BootTime.QuadPart)/10000;
}
|
请发表评论