2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/time.c
5 * PURPOSE: Time and Timezone Management
6 * PROGRAMMERS: Eric Kohl
10 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 #define TICKSPERMINUTE 600000000
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, ExpInitTimeZoneInfo)
22 /* GLOBALS ******************************************************************/
24 /* Note: Bias[minutes] = UTC - local time */
25 TIME_ZONE_INFORMATION ExpTimeZoneInfo
;
26 LARGE_INTEGER ExpTimeZoneBias
;
29 /* FUNCTIONS ****************************************************************/
34 ExpInitTimeZoneInfo(VOID
)
36 LARGE_INTEGER CurrentTime
;
39 /* Read time zone information from the registry */
40 Status
= RtlQueryTimeZoneInformation(&ExpTimeZoneInfo
);
41 if (!NT_SUCCESS(Status
))
43 /* Failed, clear all data */
44 RtlZeroMemory(&ExpTimeZoneInfo
, sizeof(TIME_ZONE_INFORMATION
));
45 ExpTimeZoneBias
.QuadPart
= (LONGLONG
)0;
46 ExpTimeZoneId
= TIME_ZONE_ID_UNKNOWN
;
50 /* FIXME: Calculate transition dates */
53 ExpTimeZoneBias
.QuadPart
= ((LONGLONG
)(ExpTimeZoneInfo
.Bias
+
54 ExpTimeZoneInfo
.StandardBias
)) *
56 ExpTimeZoneId
= TIME_ZONE_ID_STANDARD
;
59 /* Change it for user-mode applications */
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
;
65 /* Convert boot time from local time to UTC */
66 SystemBootTime
.QuadPart
+= ExpTimeZoneBias
.QuadPart
;
68 /* Convert system time from local time to UTC */
71 CurrentTime
.u
.HighPart
= SharedUserData
->SystemTime
.High1Time
;
72 CurrentTime
.u
.LowPart
= SharedUserData
->SystemTime
.LowPart
;
73 } while (CurrentTime
.u
.HighPart
!= SharedUserData
->SystemTime
.High2Time
);
75 /* Change it for user-mode applications */
76 CurrentTime
.QuadPart
+= ExpTimeZoneBias
.QuadPart
;
77 SharedUserData
->SystemTime
.LowPart
= CurrentTime
.u
.LowPart
;
78 SharedUserData
->SystemTime
.High1Time
= CurrentTime
.u
.HighPart
;
79 SharedUserData
->SystemTime
.High2Time
= CurrentTime
.u
.HighPart
;
83 ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation
)
85 LARGE_INTEGER LocalTime
, SystemTime
;
86 TIME_FIELDS TimeFields
;
87 DPRINT("ExpSetTimeZoneInformation() called\n");
89 DPRINT("Old time zone bias: %d minutes\n", ExpTimeZoneInfo
.Bias
);
90 DPRINT("Old time zone standard bias: %d minutes\n",
91 ExpTimeZoneInfo
.StandardBias
);
92 DPRINT("New time zone bias: %d minutes\n", TimeZoneInformation
->Bias
);
93 DPRINT("New time zone standard bias: %d minutes\n",
94 TimeZoneInformation
->StandardBias
);
96 /* Get the local time */
97 HalQueryRealTimeClock(&TimeFields
);
98 RtlTimeFieldsToTime(&TimeFields
, &LocalTime
);
100 /* FIXME: Calculate transition dates */
102 /* Calculate the bias and set the ID */
103 ExpTimeZoneBias
.QuadPart
= ((LONGLONG
)(TimeZoneInformation
->Bias
+
104 TimeZoneInformation
->StandardBias
)) *
106 ExpTimeZoneId
= TIME_ZONE_ID_STANDARD
;
108 /* Copy the timezone information */
109 RtlMoveMemory(&ExpTimeZoneInfo
,
111 sizeof(TIME_ZONE_INFORMATION
));
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
;
119 DPRINT("New time zone bias: %I64d minutes\n",
120 ExpTimeZoneBias
.QuadPart
/ TICKSPERMINUTE
);
122 /* Calculate the new system time */
123 ExLocalTimeToSystemTime(&LocalTime
, &SystemTime
);
125 /* Set the new system time */
126 KiSetSystemTime(&SystemTime
);
129 DPRINT("ExpSetTimeZoneInformation() done\n");
130 return STATUS_SUCCESS
;
134 * FUNCTION: Sets the system time.
136 * NewTime - Points to a variable that specified the new time
137 * of day in the standard time format.
138 * OldTime - Optionally points to a variable that receives the
139 * old time of day in the standard time format.
144 NtSetSystemTime(IN PLARGE_INTEGER SystemTime
,
145 OUT PLARGE_INTEGER PreviousTime OPTIONAL
)
147 LARGE_INTEGER OldSystemTime
;
148 LARGE_INTEGER NewSystemTime
;
149 LARGE_INTEGER LocalTime
;
150 TIME_FIELDS TimeFields
;
151 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
152 NTSTATUS Status
= STATUS_SUCCESS
;
155 /* Check if we were called from user-mode */
156 if(PreviousMode
!= KernelMode
)
160 /* Verify the time pointers */
161 NewSystemTime
= ProbeForReadLargeInteger(SystemTime
);
162 if(PreviousTime
) ProbeForWriteLargeInteger(PreviousTime
);
164 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
166 Status
= _SEH_GetExceptionCode();
170 /* If the pointers were invalid, bail out */
171 if(!NT_SUCCESS(Status
)) return Status
;
175 /* Reuse the pointer */
176 NewSystemTime
= *SystemTime
;
179 /* Make sure we have permission to change the time */
180 if(!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
182 DPRINT1("NtSetSystemTime: Caller requires the "
183 "SeSystemtimePrivilege privilege!\n");
184 return STATUS_PRIVILEGE_NOT_HELD
;
187 /* Check if caller wants the old time */
188 if(PreviousTime
) KeQuerySystemTime(&OldSystemTime
);
190 /* Convert the time and set it in HAL */
191 ExSystemTimeToLocalTime(&NewSystemTime
, &LocalTime
);
192 RtlTimeToTimeFields(&LocalTime
, &TimeFields
);
193 HalSetRealTimeClock(&TimeFields
);
195 /* Now set system time */
196 KiSetSystemTime(&NewSystemTime
);
198 /* Check if caller wanted previous time */
201 /* Enter SEH Block for return */
204 /* Return the previous time */
205 *PreviousTime
= OldSystemTime
;
207 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
209 Status
= _SEH_GetExceptionCode();
219 * FUNCTION: Retrieves the system time.
221 * CurrentTime - Points to a variable that receives the current
222 * time of day in the standard time format.
226 NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime
)
228 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
229 NTSTATUS Status
= STATUS_SUCCESS
;
232 /* Check if we were called from user-mode */
233 if(PreviousMode
!= KernelMode
)
237 /* Verify the time pointer */
238 ProbeForWriteLargeInteger(SystemTime
);
241 * It's safe to pass the pointer directly to KeQuerySystemTime as
242 * it's just a basic copy to this pointer. If it raises an
243 * exception nothing dangerous can happen!
245 KeQuerySystemTime(SystemTime
);
247 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
249 Status
= _SEH_GetExceptionCode();
255 /* Query the time directly */
256 KeQuerySystemTime(SystemTime
);
259 /* Return status to caller */
268 ExLocalTimeToSystemTime(PLARGE_INTEGER LocalTime
,
269 PLARGE_INTEGER SystemTime
)
271 SystemTime
->QuadPart
= LocalTime
->QuadPart
+ ExpTimeZoneBias
.QuadPart
;
279 ExSetTimerResolution(IN ULONG DesiredTime
,
280 IN BOOLEAN SetResolution
)
291 ExSystemTimeToLocalTime(PLARGE_INTEGER SystemTime
,
292 PLARGE_INTEGER LocalTime
)
294 LocalTime
->QuadPart
= SystemTime
->QuadPart
- ExpTimeZoneBias
.QuadPart
;