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