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