[Any Version] "Clock Overrun" bug fix

Hey Shavit, that's a problem I've been encountering with my client for years.
We documented this problem on our team's drive folder long ago and the solution was to simply perform a full shutdown on the player's PC every 25 days before running the client launcher.

Would you please explain how this piece of code fixes this issue? From what I understood, you're basically making a new counter, but how does it fix the issue when the time overflows and becomes negative? Won't a negative value % int_max result in a negative value as well?
I'd like to know the logic behind doing this
Code:
(g_real_timeGetTime() - g_iTimeGetTime) % INT32_MAX;

Also, I'd like to add that the following expression is false since this bug happens on Windows 7 as well (tested) and I remember it happening in Windows XP as well.

Code:
// bug started with windows 8
	if(!IsWindows8OrGreater())
	{
		return;
	}

Also, I'm wondering how'd you check if this actually works? lol, did you actually wait for 25/50 days to fully confirm it, or did you incidentally bug the clock?

Thanks!
 
I'm sure you're here because of my reply on StackOverflow


The modulo operator makes sure it'll never overflow to negative.
Nexon uses signed comparisons (debug symbols hint they use `int` instead of `ulong` or `DWORD`).
Imagine it being cast like so:

Code:
DWORD dwProperTime = timeGetTime(); // this is an unsigned long
int nWrongTimeImplicit = dwProperTime;
int nWrongTimeExplicit1 = (int) dwProperTime;
int nWrongTimeExplicit2 = reinterpret_cast<int>(dwProperTime);

When casted to int, the last 4 bytes of dwProperTime will be ignored; so you're stuck at the exact same number.
Nexon sometimes uses an int instead of the proper DWORD/ulong to store this number. As a result, it can overflow to negative after 24.8 days of system uptime and the game isn't designed to handle negative durations.



The logic is counting from 0 rather than from your system's uptime, as well as using modulo so we never overflow above 0x7FFFFFFF.



I don't know why, but I can't get the timeGetTime hook to work on operating systems older than Windows 8. `timeGetTime` seems to be null when using the Windows 10 SDK to build the DLL, as well as `GetProcAddress(LoadLibraryA("KERNEL32"), "timeGetTime")` not exactly being on our side.

It seems like timeGetTime is not a part of kernel32.dll unlike GetTickCount, it's a part of winmm.dll.
 
suck a fat dick
 
Last edited:
Looking at it once again on MSDN, it seems like you're right. However I'm confused about why the code still executes fine on newer versions of Windows if that's the case.

I tested hooking timeGetTime from winmm.dll on Windows 10 and it worked fine. I don't see how it would even work when referencing the function from kernel32.dll, where it doesn't exist. Perhaps just a little miss on your side :wink:
You still haven't told me how you confirmed that the solution was working, lol. Maybe you thought it was working with timeGetTime since GetTickCount is the culprit for some of the major bugs that the issue causes? (godmode being one of them)
 
suck a fat dick
 
Last edited:
I did some further testing and winmm.dll seems to be loaded dynamically by KERNEL32 when running Windows 10, but it doesn't on Windows 7. Which is why GetProcAddress on it works there.

My testing was simply using a server machine which isn't being rebooted at all.

Well then, problem solved!
 
Back