use inlined probing macros for basic types
[reactos.git] / reactos / ntoskrnl / ex / time.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/time.c
6 * PURPOSE: Time
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17
18 #define TICKSPERMINUTE 600000000
19
20 /* GLOBALS ******************************************************************/
21
22 /* Note: Bias[minutes] = UTC - local time */
23 TIME_ZONE_INFORMATION ExpTimeZoneInfo;
24 LARGE_INTEGER ExpTimeZoneBias;
25 ULONG ExpTimeZoneId;
26
27
28 /* FUNCTIONS ****************************************************************/
29
30 VOID
31 INIT_FUNCTION
32 STDCALL
33 ExpInitTimeZoneInfo(VOID)
34 {
35 LARGE_INTEGER CurrentTime;
36 NTSTATUS Status;
37
38 /* Read time zone information from the registry */
39 Status = RtlQueryTimeZoneInformation(&ExpTimeZoneInfo);
40 if (!NT_SUCCESS(Status))
41 {
42 memset(&ExpTimeZoneInfo, 0, sizeof(TIME_ZONE_INFORMATION));
43
44 ExpTimeZoneBias.QuadPart = (LONGLONG)0;
45 ExpTimeZoneId = TIME_ZONE_ID_UNKNOWN;
46 }
47 else
48 {
49 /* FIXME: Calculate transition dates */
50
51 ExpTimeZoneBias.QuadPart =
52 ((LONGLONG)(ExpTimeZoneInfo.Bias + ExpTimeZoneInfo.StandardBias)) * TICKSPERMINUTE;
53 ExpTimeZoneId = TIME_ZONE_ID_STANDARD;
54 }
55
56 SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.u.HighPart;
57 SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.u.HighPart;
58 SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.u.LowPart;
59 SharedUserData->TimeZoneId = ExpTimeZoneId;
60
61 /* Convert boot time from local time to UTC */
62 SystemBootTime.QuadPart += ExpTimeZoneBias.QuadPart;
63
64 /* Convert sytem time from local time to UTC */
65 do
66 {
67 CurrentTime.u.HighPart = SharedUserData->SystemTime.High1Time;
68 CurrentTime.u.LowPart = SharedUserData->SystemTime.LowPart;
69 }
70 while (CurrentTime.u.HighPart != SharedUserData->SystemTime.High2Time);
71
72 CurrentTime.QuadPart += ExpTimeZoneBias.QuadPart;
73
74 SharedUserData->SystemTime.LowPart = CurrentTime.u.LowPart;
75 SharedUserData->SystemTime.High1Time = CurrentTime.u.HighPart;
76 SharedUserData->SystemTime.High2Time = CurrentTime.u.HighPart;
77 }
78
79
80 NTSTATUS
81 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation)
82 {
83 LARGE_INTEGER LocalTime;
84 LARGE_INTEGER SystemTime;
85 TIME_FIELDS TimeFields;
86
87 DPRINT("ExpSetTimeZoneInformation() called\n");
88
89 DPRINT("Old time zone bias: %d minutes\n",
90 ExpTimeZoneInfo.Bias);
91 DPRINT("Old time zone standard bias: %d minutes\n",
92 ExpTimeZoneInfo.StandardBias);
93
94 DPRINT("New time zone bias: %d minutes\n",
95 TimeZoneInformation->Bias);
96 DPRINT("New time zone standard bias: %d minutes\n",
97 TimeZoneInformation->StandardBias);
98
99 /* Get the local time */
100 HalQueryRealTimeClock(&TimeFields);
101 RtlTimeFieldsToTime(&TimeFields,
102 &LocalTime);
103
104 /* FIXME: Calculate transition dates */
105
106 ExpTimeZoneBias.QuadPart =
107 ((LONGLONG)(TimeZoneInformation->Bias + TimeZoneInformation->StandardBias)) * TICKSPERMINUTE;
108 ExpTimeZoneId = TIME_ZONE_ID_STANDARD;
109
110 memcpy(&ExpTimeZoneInfo,
111 TimeZoneInformation,
112 sizeof(TIME_ZONE_INFORMATION));
113
114 /* Set the new time zone information */
115 SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.u.HighPart;
116 SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.u.HighPart;
117 SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.u.LowPart;
118 SharedUserData->TimeZoneId = ExpTimeZoneId;
119
120 DPRINT("New time zone bias: %I64d minutes\n",
121 ExpTimeZoneBias.QuadPart / TICKSPERMINUTE);
122
123 /* Calculate the new system time */
124 ExLocalTimeToSystemTime(&LocalTime,
125 &SystemTime);
126
127 /* Set the new system time */
128 KiSetSystemTime(&SystemTime);
129
130 DPRINT("ExpSetTimeZoneInformation() done\n");
131
132 return STATUS_SUCCESS;
133 }
134
135
136 /*
137 * FUNCTION: Sets the system time.
138 * PARAMETERS:
139 * NewTime - Points to a variable that specified the new time
140 * of day in the standard time format.
141 * OldTime - Optionally points to a variable that receives the
142 * old time of day in the standard time format.
143 * RETURNS: Status
144 */
145 NTSTATUS STDCALL
146 NtSetSystemTime(IN PLARGE_INTEGER SystemTime,
147 OUT PLARGE_INTEGER PreviousTime OPTIONAL)
148 {
149 LARGE_INTEGER OldSystemTime;
150 LARGE_INTEGER NewSystemTime;
151 LARGE_INTEGER LocalTime;
152 TIME_FIELDS TimeFields;
153 KPROCESSOR_MODE PreviousMode;
154 NTSTATUS Status = STATUS_SUCCESS;
155
156 PAGED_CODE();
157
158 PreviousMode = ExGetPreviousMode();
159
160 if(PreviousMode != KernelMode)
161 {
162 _SEH_TRY
163 {
164 NewSystemTime = ProbeForReadLargeInteger(SystemTime);
165 if(PreviousTime != NULL)
166 {
167 ProbeForWriteLargeInteger(PreviousTime);
168 }
169 }
170 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
171 {
172 Status = _SEH_GetExceptionCode();
173 }
174 _SEH_END;
175
176 if(!NT_SUCCESS(Status))
177 {
178 return Status;
179 }
180 }
181 else
182 {
183 NewSystemTime = *SystemTime;
184 }
185
186 if(!SeSinglePrivilegeCheck(SeSystemtimePrivilege,
187 PreviousMode))
188 {
189 DPRINT1("NtSetSystemTime: Caller requires the SeSystemtimePrivilege privilege!\n");
190 return STATUS_PRIVILEGE_NOT_HELD;
191 }
192
193 if(PreviousTime != NULL)
194 {
195 KeQuerySystemTime(&OldSystemTime);
196 }
197
198 ExSystemTimeToLocalTime(&NewSystemTime,
199 &LocalTime);
200 RtlTimeToTimeFields(&LocalTime,
201 &TimeFields);
202 HalSetRealTimeClock(&TimeFields);
203
204 /* Set system time */
205 KiSetSystemTime(&NewSystemTime);
206
207 if(PreviousTime != NULL)
208 {
209 _SEH_TRY
210 {
211 *PreviousTime = OldSystemTime;
212 }
213 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
214 {
215 Status = _SEH_GetExceptionCode();
216 }
217 _SEH_END;
218 }
219
220 return STATUS_SUCCESS;
221 }
222
223
224 /*
225 * FUNCTION: Retrieves the system time.
226 * PARAMETERS:
227 * CurrentTime - Points to a variable that receives the current
228 * time of day in the standard time format.
229 */
230 NTSTATUS STDCALL
231 NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
232 {
233 KPROCESSOR_MODE PreviousMode;
234 NTSTATUS Status = STATUS_SUCCESS;
235
236 PAGED_CODE();
237
238 PreviousMode = ExGetPreviousMode();
239
240 if(PreviousMode != KernelMode)
241 {
242 _SEH_TRY
243 {
244 ProbeForWriteLargeInteger(SystemTime);
245
246 /* it's safe to pass the pointer directly to KeQuerySystemTime as it's just
247 a basic copy to these pointer, if it raises an exception nothing dangerous
248 can happen! */
249 KeQuerySystemTime(SystemTime);
250 }
251 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
252 {
253 Status = _SEH_GetExceptionCode();
254 }
255 _SEH_END;
256 }
257 else
258 {
259 KeQuerySystemTime(SystemTime);
260 }
261
262 return Status;
263 }
264
265
266 /*
267 * @implemented
268 */
269 VOID
270 STDCALL
271 ExLocalTimeToSystemTime (
272 PLARGE_INTEGER LocalTime,
273 PLARGE_INTEGER SystemTime
274 )
275 {
276 SystemTime->QuadPart =
277 LocalTime->QuadPart + ExpTimeZoneBias.QuadPart;
278 }
279
280
281 /*
282 * @unimplemented
283 */
284 ULONG
285 STDCALL
286 ExSetTimerResolution (
287 IN ULONG DesiredTime,
288 IN BOOLEAN SetResolution
289 )
290 {
291 UNIMPLEMENTED;
292
293 return 0;
294 }
295
296
297 /*
298 * @implemented
299 */
300 VOID
301 STDCALL
302 ExSystemTimeToLocalTime (
303 PLARGE_INTEGER SystemTime,
304 PLARGE_INTEGER LocalTime
305 )
306 {
307 LocalTime->QuadPart =
308 SystemTime->QuadPart - ExpTimeZoneBias.QuadPart;
309 }
310
311 /* EOF */