diff options
| author | pravic <[email protected]> | 2016-04-14 00:01:22 +0300 |
|---|---|---|
| committer | pravic <[email protected]> | 2016-04-14 00:01:22 +0300 |
| commit | b365946875e776e271b3e91bb042a999acdb408b (patch) | |
| tree | 7a1dc905b97a4994c98985c31695b19b86228ddf | |
| parent | note about staticlib compilation (diff) | |
| download | winapi-kmd-rs-b365946875e776e271b3e91bb042a999acdb408b.tar.xz winapi-kmd-rs-b365946875e776e271b3e91bb042a999acdb408b.zip | |
implement KeQuerySystemTime routine for x64 kernel, since it exported only at x86.
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/shared.rs | 153 | ||||
| -rw-r--r-- | src/time.rs | 32 |
3 files changed, 184 insertions, 2 deletions
@@ -27,6 +27,7 @@ pub mod irql; pub mod object; pub mod pool; pub mod rtl; +pub mod shared; pub mod string; pub mod time; diff --git a/src/shared.rs b/src/shared.rs new file mode 100644 index 0000000..acd572b --- /dev/null +++ b/src/shared.rs @@ -0,0 +1,153 @@ +//! Data shared between kernel and user mode. + + +/// System time is a count of 100-nanosecond intervals since January 1, 1601. +pub type SYSTEMTIME = i64; + + +/// Dystem time structure +#[repr(C)] +#[derive(Copy, Clone)] +pub struct KSYSTEM_TIME +{ + LowPart: u32, + High1Time: i32, + High2Time: i32, +} + +#[repr(C)] +pub enum NT_PRODUCT_TYPE +{ + NtProductWinNt = 1, + NtProductLanManNt, + NtProductServer +} + +#[repr(C)] +pub enum ALTERNATIVE_ARCHITECTURE_TYPE +{ + StandardDesign, + NEC98x86, + EndAlternatives, +} + +/// The data shared between kernel and user mode. +#[repr(C)] +pub struct KUSER_SHARED_DATA +{ + pub TickCountLowDeprecated: u32, + pub TickCountMultiplier: u32, + + /// Current 64-bit interrupt time in 100ns units. + pub InterruptTime: KSYSTEM_TIME, + /// Current 64-bit system time in 100ns units. + pub SystemTime: KSYSTEM_TIME, + /// Current 64-bit time zone bias. + pub TimeZoneBias: KSYSTEM_TIME, + + pub ImageNumberLow: u16, + pub ImageNumberHigh: u16, + + pub NtSystemRoot: [u16; 260], + + pub MaxStackTraceDepth: u32, + pub CryptoExponent: u32, + pub TimeZoneId: u32, + pub LargePageMinimum: u32, + pub Reserved2: [u32; 7], + + pub NtProductType: NT_PRODUCT_TYPE, + pub ProductTypeIsValid: bool, + pub NtMajorVersion: u32, + pub NtMinorVersion: u32, + + pub ProcessorFeatures: [bool; 64], + pub Reserved1: u32, + pub Reserved3: u32, + pub TimeSlip: u32, + + pub AlternativeArchitecture: ALTERNATIVE_ARCHITECTURE_TYPE, + pub SystemExpirationDate: u64, + pub SuiteMask: u32, + + /// True if a kernel debugger is connected/enabled. + pub KdDebuggerEnabled: bool, + pub NXSupportPolicy: u8, + pub ActiveConsoleId: u32, + pub DismountCount: u32, + pub ComPlusPackage: u32, + pub LastSystemRITEventTickCount: u32, + pub NumberOfPhysicalPages: u32, + + /// True if the system was booted in safe boot mode. + pub SafeBootMode: bool, + pub TraceLogging: u32, + + pub TestRetInstruction: u64, + pub SystemCall: u32, + pub SystemCallReturn: u32, + pub SystemCallPad: [u64; 3], + + /// The 64-bit tick count. + pub TickCount: KSYSTEM_TIME, + + /// Cookie for encoding pointers system wide. + pub Cookie: u32, + + // NT 6.0+: + + #[cfg(target_arch = "x86_64")] + pub Wow64SharedInformation: [u32; 16], + #[cfg(target_arch = "x86_64")] + pub UserModeGlobalLogger: [u16; 8], + #[cfg(target_arch = "x86_64")] + pub HeapTracingPid: [u32; 2], + #[cfg(target_arch = "x86_64")] + pub CritSecTracingPid: [u32; 2], + #[cfg(target_arch = "x86_64")] + pub ImageFileExecutionOptions: u32, + #[cfg(target_arch = "x86_64")] + pub ActiveProcessorAffinity: u64, + #[cfg(target_arch = "x86_64")] + pub InterruptTimeBias: u64, +} + +#[cfg(target_arch = "x86")] +const KI_USER_SHARED_DATA: *const KUSER_SHARED_DATA = 0xffdf_0000 as *const KUSER_SHARED_DATA; + +#[cfg(target_arch = "x86_64")] +const KI_USER_SHARED_DATA: *const KUSER_SHARED_DATA = 0xFFFF_F780_0000_0000 as *const KUSER_SHARED_DATA; + +impl KUSER_SHARED_DATA { + + /// Get reference to the mapped shared data. + pub fn get() -> &'static KUSER_SHARED_DATA { + unsafe { &*KI_USER_SHARED_DATA } + } +} + +/// Convert `KSYSTEM_TIME` to `i64` +#[cfg(target_arch = "x86_64")] +impl ::core::convert::From<KSYSTEM_TIME> for SYSTEMTIME { + fn from(time: KSYSTEM_TIME) -> Self { + unsafe { *(&time as *const KSYSTEM_TIME as *const SYSTEMTIME) } + } +} + +/// Convert `KSYSTEM_TIME` to `i64` +#[cfg(target_arch = "x86")] +impl ::core::convert::From<KSYSTEM_TIME> for SYSTEMTIME { + fn from(time: KSYSTEM_TIME) -> Self { + // FIXME: is any `volatile` or memory fenses need here? + let mut lo; + let mut hi; + loop { + hi = time.High1Time; + lo = time.LowPart; + if hi == time.High2Time { + break; + } + } + return (hi as i64) << 32 | lo as i64 + } +} diff --git a/src/time.rs b/src/time.rs index b4d0e99..eac3bc3 100644 --- a/src/time.rs +++ b/src/time.rs @@ -1,26 +1,54 @@ //! NT Time routines. -/// System time is a count of 100-nanosecond intervals since January 1, 1601. -pub type SYSTEMTIME = i64; +use ::shared::{SYSTEMTIME}; + +#[cfg(target_arch = "x86_64")] +use ::shared::{KUSER_SHARED_DATA}; + extern "system" { + // The following exports exists only on x86 kernels. + // x64 drivers must use KUSER_SHARED_DATA to obtain these values. + + #[cfg(target_arch = "x86")] fn KeQuerySystemTime(CurrentTime: *mut SYSTEMTIME); + #[cfg(target_arch = "x86")] fn KeQueryTickCount(TickCount: *mut i64); + /// Converts a GMT system time value to the local system time for the current time zone. pub fn ExSystemTimeToLocalTime(SystemTime: *const SYSTEMTIME, LocalTime: *mut SYSTEMTIME); } + /// Obtains the current system time. +#[cfg(target_arch = "x86")] pub fn QuerySystemTime() -> SYSTEMTIME { let mut t = 0i64; unsafe { KeQuerySystemTime(&mut t) }; return t; } +/// Obtains the current system time. +#[cfg(target_arch = "x86_64")] +pub fn QuerySystemTime() -> SYSTEMTIME { + let shared = KUSER_SHARED_DATA::get(); + SYSTEMTIME::from(shared.SystemTime) +} + + /// A count of the interval timer interrupts that have occurred since the system was booted. +#[cfg(target_arch = "x86")] pub fn QueryTickCount() -> i64 { let mut t = 0i64; unsafe { KeQueryTickCount(&mut t) }; return t; } + + +/// A count of the interval timer interrupts that have occurred since the system was booted. +#[cfg(target_arch = "x86_64")] +pub fn QueryTickCount() -> i64 { + let shared = KUSER_SHARED_DATA::get(); + SYSTEMTIME::from(shared.TickCount) +} |