delphi windows xp 无GetTickCount64解决方案

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;

}