1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
	}
}