/** * @file PlatformTime.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Implementation of cross platform APIs for system time operations * @details * @version 0.19 * @date 2026-05-09 * * @copyright This project is released under the GNU Public License v3. * */ #include "pch.h" #if defined(__linux__) # include "../header/PlatformTime.h" # include // ktime_get_real_ts64 # include // time64_to_tm, struct tm, sys_tz // // Windows kernel time is 100-nanosecond ticks since 1601-01-01; Linux gives // Unix-epoch (1970) seconds. These bridge the two. // # define HUNDRED_NS_PER_SEC 10000000LL # define EPOCH_DIFF_1601_TO_1970_SECS 11644473600LL #endif // defined(__linux__) /** * @brief Query the current system time * * @param SystemTime Receives the current system time as a LARGE_INTEGER (100-nanosecond units since January 1, 1601) * @return VOID */ VOID PlatformTimeQuerySystemTime(PLARGE_INTEGER SystemTime) { #if defined(_WIN32) || defined(_WIN64) KeQuerySystemTime(SystemTime); #elif defined(__linux__) struct timespec64 Ts; ktime_get_real_ts64(&Ts); // // Shift Unix epoch (1970) → NT epoch (1601) and rescale sec/nsec to 100-ns. // SystemTime->QuadPart = ((LONGLONG)Ts.tv_sec + EPOCH_DIFF_1601_TO_1970_SECS) * HUNDRED_NS_PER_SEC + Ts.tv_nsec / 100; #else # error "Unsupported platform" #endif } /** * @brief Convert system time (UTC) to local time * * @param SystemTime Pointer to the system time value in UTC * @param LocalTime Receives the converted local time value * @return VOID */ VOID PlatformTimeConvertToLocalTime(PLARGE_INTEGER SystemTime, PLARGE_INTEGER LocalTime) { #if defined(_WIN32) || defined(_WIN64) ExSystemTimeToLocalTime(SystemTime, LocalTime); #elif defined(__linux__) // // Apply the kernel's timezone bias (minutes west of UTC). sys_tz is 0 on // systems that keep the RTC in UTC, in which case LocalTime == SystemTime. // LocalTime->QuadPart = SystemTime->QuadPart - (LONGLONG)sys_tz.tz_minuteswest * 60 * HUNDRED_NS_PER_SEC; #else # error "Unsupported platform" #endif } /** * @brief Convert a LARGE_INTEGER time value to a TIME_FIELDS structure * * @param Time Pointer to the time value to convert * @param TimeFields Receives the broken-down time fields (year, month, day, hour, minute, etc.) * @return VOID */ VOID PlatformTimeConvertToTimeFields(PLARGE_INTEGER Time, PTIME_FIELDS TimeFields) { #if defined(_WIN32) || defined(_WIN64) RtlTimeToTimeFields(Time, TimeFields); #elif defined(__linux__) struct tm Tm; LONGLONG Ticks = Time->QuadPart; time64_t UnixSec = (time64_t)(Ticks / HUNDRED_NS_PER_SEC) - EPOCH_DIFF_1601_TO_1970_SECS; SHORT Msec = (SHORT)((Ticks % HUNDRED_NS_PER_SEC) / 10000); time64_to_tm(UnixSec, 0, &Tm); TimeFields->Year = (SHORT)(Tm.tm_year + 1900); // tm_year is years since 1900 TimeFields->Month = (SHORT)(Tm.tm_mon + 1); // tm_mon is 0..11 TimeFields->Day = (SHORT)Tm.tm_mday; TimeFields->Hour = (SHORT)Tm.tm_hour; TimeFields->Minute = (SHORT)Tm.tm_min; TimeFields->Second = (SHORT)Tm.tm_sec; TimeFields->Milliseconds = Msec; TimeFields->Weekday = (SHORT)Tm.tm_wday; // both count from Sunday = 0 #else # error "Unsupported platform" #endif }