From 767950661f91dc88d9534bc8f94a73205e338a97 Mon Sep 17 00:00:00 2001 From: Collin Funk Date: Fri, 24 May 2024 19:23:25 -0700 Subject: [PATCH] boot-time, readutmp: Add a Native Windows boot time fallback. * lib/boot-time-aux.h (initialize, get_windows_boot_time_fallback): New functions. * lib/boot-time.c [_WIN32 && !__CYGWIN__]: Include Windows headers and . (get_boot_time_uncached): Use the fallback. * lib/readutmp.c [_WIN32 && !__CYGWIN__]: Include Windows headers and . (read_utmp_from_file): Use the fallback. * modules/boot-time (Depends-on): Add gettimeofday. * modules/readutmp (Depends-on): Add gettimeofday. --- ChangeLog | 14 +++++++++ lib/boot-time-aux.h | 74 +++++++++++++++++++++++++++++++++++++++++++++ lib/boot-time.c | 11 +++++++ lib/readutmp.c | 23 ++++++++++++++ modules/boot-time | 1 + modules/readutmp | 1 + 6 files changed, 124 insertions(+) diff --git a/ChangeLog b/ChangeLog index e46a1a7572..12c2600d7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2024-05-24 Collin Funk + + boot-time, readutmp: Add a Native Windows boot time fallback. + * lib/boot-time-aux.h (initialize, get_windows_boot_time_fallback): New + functions. + * lib/boot-time.c [_WIN32 && !__CYGWIN__]: Include Windows headers and + . + (get_boot_time_uncached): Use the fallback. + * lib/readutmp.c [_WIN32 && !__CYGWIN__]: Include Windows headers and + . + (read_utmp_from_file): Use the fallback. + * modules/boot-time (Depends-on): Add gettimeofday. + * modules/readutmp (Depends-on): Add gettimeofday. + 2024-05-23 Bruno Haible mbrtoc32: Work around bug in Cygwin 3.5.3. diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h index b1add30239..8b98c4e573 100644 --- a/lib/boot-time-aux.h +++ b/lib/boot-time-aux.h @@ -345,4 +345,78 @@ get_windows_boot_time (struct timespec *p_boot_time) return -1; } +# ifndef __CYGWIN__ +# if !(_WIN32_WINNT >= _WIN32_WINNT_VISTA) + +/* Don't assume that UNICODE is not defined. */ +# undef LoadLibrary +# define LoadLibrary LoadLibraryA + +/* Avoid warnings from gcc -Wcast-function-type. */ +# define GetProcAddress \ + (void *) GetProcAddress + +/* GetTickCount64 is only available on Windows Vista and later. */ +typedef ULONGLONG (WINAPI * GetTickCount64FuncType) (void); + +static GetTickCount64FuncType GetTickCount64Func = NULL; +static BOOL initialized = FALSE; + +static void +initialize (void) +{ + HMODULE kernel32 = LoadLibrary ("kernel32.dll"); + if (kernel32 != NULL) + { + GetTickCount64Func = + (GetTickCount64FuncType) GetProcAddress (kernel32, "GetTickCount64"); + } + initialized = TRUE; +} + +# else + +# define GetTickCount64Func GetTickCount64 + +# endif + +/* Fallback for Windows in the form: + boot time = current time - uptime + This uses the GetTickCount64 function which is only available on Windows + Vista and later. See: + . */ +static int +get_windows_boot_time_fallback (struct timespec *p_boot_time) +{ +# if !(_WIN32_WINNT >= _WIN32_WINNT_VISTA) + if (! initialized) + initialize (); +# endif + if (GetTickCount64Func != NULL) + { + ULONGLONG uptime_ms = GetTickCount64Func (); + struct timespec uptime; + struct timespec result; + struct timeval tv; + if (gettimeofday (&tv, NULL) >= 0) + { + uptime.tv_sec = uptime_ms / 1000; + uptime.tv_nsec = (uptime_ms % 1000) * 1000000; + result.tv_sec = tv.tv_sec; + result.tv_nsec = tv.tv_usec * 1000; + if (result.tv_nsec < uptime.tv_nsec) + { + result.tv_nsec += 1000000000; + result.tv_sec -= 1; + } + result.tv_sec -= uptime.tv_sec; + result.tv_nsec -= uptime.tv_nsec; + *p_boot_time = result; + return 0; + } + } + return -1; +} + +# endif #endif diff --git a/lib/boot-time.c b/lib/boot-time.c index c1171e8024..71562dcf75 100644 --- a/lib/boot-time.c +++ b/lib/boot-time.c @@ -43,6 +43,13 @@ # include #endif +#if defined _WIN32 && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +# include +# include +#endif + #include "idx.h" #include "readutmp.h" #include "stat-time.h" @@ -247,6 +254,10 @@ get_boot_time_uncached (struct timespec *p_boot_time) { /* Workaround for Windows: */ get_windows_boot_time (&found_boot_time); +# ifndef __CYGWIN__ + if (found_boot_time.tv_sec == 0) + get_windows_boot_time_fallback (&found_boot_time); +# endif } # endif diff --git a/lib/readutmp.c b/lib/readutmp.c index ae2e3ae8c6..82b9d4ca33 100644 --- a/lib/readutmp.c +++ b/lib/readutmp.c @@ -51,6 +51,13 @@ # include #endif +#if defined _WIN32 && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +# include +# include +#endif + #include "stat-time.h" #include "xalloc.h" @@ -666,6 +673,22 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, } # endif +# if defined _WIN32 && ! defined __CYGWIN__ + if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0 + && strcmp (file, UTMP_FILE) == 0 + && !have_boot_time (a)) + { + struct timespec boot_time; + if (get_windows_boot_time_fallback (&boot_time) >= 0) + a = add_utmp (a, options, + "reboot", strlen ("reboot"), + "", 0, + "", 0, + "", 0, + 0, BOOT_TIME, boot_time, 0, 0, 0); + } +# endif + a = finish_utmp (a); *n_entries = a.filled; diff --git a/modules/boot-time b/modules/boot-time index 2d89969d5c..07e5e43bc6 100644 --- a/modules/boot-time +++ b/modules/boot-time @@ -12,6 +12,7 @@ Depends-on: extensions idx stat-time +gettimeofday stdbool time-h unlocked-io-internal diff --git a/modules/readutmp b/modules/readutmp index 469a7c2256..0127099187 100644 --- a/modules/readutmp +++ b/modules/readutmp @@ -12,6 +12,7 @@ Depends-on: extensions idx stat-time +gettimeofday stdbool stdint strnlen -- 2.39.5