I’ve been using information from KUSER_SHARED_DATA
(useful overview) in various contexts in the past. Some of the first members are of type KSYSTEM_TIME
and the way they’re laid out is required due to keep ISRs non-blocking according to this source.
For reference (from wdm.h
):
typedef struct _KSYSTEM_TIME {
ULONG LowPart;
LONG High1Time;
LONG High2Time;
} KSYSTEM_TIME, *PKSYSTEM_TIME;
As we can see this is practically equivalent to a LARGE_INTEGER
/LONGLONG
apart from the second “high” member (for the above mentioned reason).
Alas, FILETIME
is (from winbase.h
):
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
… and therefore all unsigned and for all intents and purposes equivalent to a ULARGE_INTEGER
/ULONGLONG
.
Now it makes sense that KSYSTEM_TIME
can be negative as for the time zone offset (KUSER_SHARED_DATA::TimeZoneBias
) but the value range is of course “halved” for the signed version and so it limits compatibility between the structs.
But it begs the question: is it alright to coerce the fields of KSYSTEM_TIME
— if known to be a time rather than a time delta — into a FILETIME
?
PS: the SYSTEMTIME
used by FileTimeToSystemTime
/SystemTimeToFileTime
corresponds more (conceptually, not 1:1) to TIME_FIELDS
struct and is not what the above question is about.
If you disassemble
GetSystemTime()
orGetSystemTimeAsFileTime()
on x64 you will see they read the value into a single 64-bit register, so it should be safe (though not contractually guaranteed) to do so.@Luke By “not contractually guaranteed” you basically mean I am depending on implementation-defined behavior (as I already do pretty much when using
KUSER_SHARED_DATA
and the native API), right? Thanks, this helps a lot. I think this is a perfectly acceptable answer (at least to me it would be). I verified it in IDA forGetSystemTimeAsFileTime()
and you are of course right.