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