Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 1 | /* |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 2 | * Nt time functions. |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 3 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4 | * RtlTimeToTimeFields, RtlTimeFieldsToTime and defines are taken from ReactOS and |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 5 | * adapted to wine with special permissions of the author. This code is |
| 6 | * Copyright 2002 Rex Jolliff (rex@lvcablemodem.com) |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 7 | * |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 8 | * Copyright 1999 Juergen Schmied |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 9 | * Copyright 2007 Dmitry Timoshkov |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 10 | * |
| 11 | * This library is free software; you can redistribute it and/or |
| 12 | * modify it under the terms of the GNU Lesser General Public |
| 13 | * License as published by the Free Software Foundation; either |
| 14 | * version 2.1 of the License, or (at your option) any later version. |
| 15 | * |
| 16 | * This library is distributed in the hope that it will be useful, |
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 19 | * Lesser General Public License for more details. |
| 20 | * |
| 21 | * You should have received a copy of the GNU Lesser General Public |
| 22 | * License along with this library; if not, write to the Free Software |
Jonathan Ernst | 360a3f9 | 2006-05-18 14:49:52 +0200 | [diff] [blame] | 23 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 24 | */ |
| 25 | |
Patrik Stridvall | d016f81 | 2002-08-17 00:43:16 +0000 | [diff] [blame] | 26 | #include "config.h" |
Patrik Stridvall | 51e6c0c | 2002-08-31 19:04:14 +0000 | [diff] [blame] | 27 | #include "wine/port.h" |
Patrik Stridvall | d016f81 | 2002-08-17 00:43:16 +0000 | [diff] [blame] | 28 | |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 29 | #include <stdarg.h> |
Vincent Béron | ea966aa | 2002-11-27 20:14:45 +0000 | [diff] [blame] | 30 | #include <stdlib.h> |
Dmitry Timoshkov | a188662 | 2007-07-29 21:31:00 +0900 | [diff] [blame] | 31 | #include <errno.h> |
David Luyer | 26cd7a1 | 1999-03-25 15:57:35 +0000 | [diff] [blame] | 32 | #include <string.h> |
Alexandre Julliard | 25b23a0 | 2004-09-07 23:01:34 +0000 | [diff] [blame] | 33 | #include <limits.h> |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 34 | #include <time.h> |
Patrik Stridvall | d016f81 | 2002-08-17 00:43:16 +0000 | [diff] [blame] | 35 | #ifdef HAVE_SYS_TIME_H |
| 36 | # include <sys/time.h> |
| 37 | #endif |
| 38 | #ifdef HAVE_UNISTD_H |
| 39 | # include <unistd.h> |
| 40 | #endif |
Dimitrie O. Paun | 297f3d8 | 2003-01-07 20:36:20 +0000 | [diff] [blame] | 41 | |
| 42 | #define NONAMELESSUNION |
| 43 | #define NONAMELESSSTRUCT |
Ge van Geldorp | 1a1583a | 2005-11-28 17:32:54 +0100 | [diff] [blame] | 44 | #include "ntstatus.h" |
| 45 | #define WIN32_NO_STATUS |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 46 | #include "windef.h" |
Patrik Stridvall | 9c1de6d | 2002-09-12 22:07:02 +0000 | [diff] [blame] | 47 | #include "winternl.h" |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 48 | #include "wine/unicode.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 49 | #include "wine/debug.h" |
Alexandre Julliard | 462172a | 2003-04-02 22:48:59 +0000 | [diff] [blame] | 50 | #include "ntdll_misc.h" |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 51 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 52 | WINE_DEFAULT_DEBUG_CHANNEL(ntdll); |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 53 | |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 54 | static int init_tz_info(RTL_TIME_ZONE_INFORMATION *tzi); |
| 55 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 56 | static RTL_CRITICAL_SECTION TIME_tz_section; |
Mike McCormack | 6b636e3 | 2005-06-25 18:00:57 +0000 | [diff] [blame] | 57 | static RTL_CRITICAL_SECTION_DEBUG critsect_debug = |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 58 | { |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 59 | 0, 0, &TIME_tz_section, |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 60 | { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 61 | 0, 0, { (DWORD_PTR)(__FILE__ ": TIME_tz_section") } |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 62 | }; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 63 | static RTL_CRITICAL_SECTION TIME_tz_section = { &critsect_debug, -1, 0, 0, 0, 0 }; |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 64 | |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 65 | #define TICKSPERSEC 10000000 |
| 66 | #define TICKSPERMSEC 10000 |
| 67 | #define SECSPERDAY 86400 |
| 68 | #define SECSPERHOUR 3600 |
| 69 | #define SECSPERMIN 60 |
| 70 | #define MINSPERHOUR 60 |
| 71 | #define HOURSPERDAY 24 |
Alexandre Julliard | dcc3afd | 2002-12-13 20:53:04 +0000 | [diff] [blame] | 72 | #define EPOCHWEEKDAY 1 /* Jan 1, 1601 was Monday */ |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 73 | #define DAYSPERWEEK 7 |
| 74 | #define EPOCHYEAR 1601 |
| 75 | #define DAYSPERNORMALYEAR 365 |
| 76 | #define DAYSPERLEAPYEAR 366 |
| 77 | #define MONSPERYEAR 12 |
Huw Davies | 166faa4 | 2004-02-24 01:01:27 +0000 | [diff] [blame] | 78 | #define DAYSPERQUADRICENTENNIUM (365 * 400 + 97) |
| 79 | #define DAYSPERNORMALCENTURY (365 * 100 + 24) |
| 80 | #define DAYSPERNORMALQUADRENNIUM (365 * 4 + 1) |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 81 | |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 82 | /* 1601 to 1970 is 369 years plus 89 leap days */ |
Alexandre Julliard | fbef57c | 2003-03-31 01:37:04 +0000 | [diff] [blame] | 83 | #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY) |
| 84 | #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 85 | /* 1601 to 1980 is 379 years plus 91 leap days */ |
Alexandre Julliard | fbef57c | 2003-03-31 01:37:04 +0000 | [diff] [blame] | 86 | #define SECS_1601_TO_1980 ((379 * 365 + 91) * (ULONGLONG)SECSPERDAY) |
| 87 | #define TICKS_1601_TO_1980 (SECS_1601_TO_1980 * TICKSPERSEC) |
Alexandre Julliard | 25b23a0 | 2004-09-07 23:01:34 +0000 | [diff] [blame] | 88 | /* max ticks that can be represented as Unix time */ |
| 89 | #define TICKS_1601_TO_UNIX_MAX ((SECS_1601_TO_1970 + INT_MAX) * TICKSPERSEC) |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 90 | |
| 91 | |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 92 | static const int MonthLengths[2][MONSPERYEAR] = |
| 93 | { |
| 94 | { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, |
| 95 | { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } |
| 96 | }; |
| 97 | |
Patrik Stridvall | 896889f | 1999-05-08 12:50:36 +0000 | [diff] [blame] | 98 | static inline int IsLeapYear(int Year) |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 99 | { |
| 100 | return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0; |
| 101 | } |
| 102 | |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 103 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 104 | * RtlTimeToTimeFields [NTDLL.@] |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 105 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 106 | * Convert a time into a TIME_FIELDS structure. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 107 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 108 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 109 | * liTime [I] Time to convert. |
| 110 | * TimeFields [O] Destination for the converted time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 111 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 112 | * RETURNS |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 113 | * Nothing. |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 114 | */ |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 115 | VOID WINAPI RtlTimeToTimeFields( |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 116 | const LARGE_INTEGER *liTime, |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 117 | PTIME_FIELDS TimeFields) |
| 118 | { |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 119 | int SecondsInDay; |
| 120 | long int cleaps, years, yearday, months; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 121 | long int Days; |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 122 | LONGLONG Time; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 123 | |
| 124 | /* Extract millisecond from time and convert time into seconds */ |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 125 | TimeFields->Milliseconds = |
| 126 | (CSHORT) (( liTime->QuadPart % TICKSPERSEC) / TICKSPERMSEC); |
| 127 | Time = liTime->QuadPart / TICKSPERSEC; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 128 | |
György 'Nog' Jeney | 39433b9 | 2002-11-06 21:57:23 +0000 | [diff] [blame] | 129 | /* The native version of RtlTimeToTimeFields does not take leap seconds |
| 130 | * into account */ |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 131 | |
| 132 | /* Split the time into days and seconds within the day */ |
| 133 | Days = Time / SECSPERDAY; |
| 134 | SecondsInDay = Time % SECSPERDAY; |
| 135 | |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 136 | /* compute time of day */ |
| 137 | TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR); |
| 138 | SecondsInDay = SecondsInDay % SECSPERHOUR; |
| 139 | TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN); |
| 140 | TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN); |
| 141 | |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 142 | /* compute day of week */ |
| 143 | TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK); |
| 144 | |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 145 | /* compute year, month and day of month. */ |
| 146 | cleaps=( 3 * ((4 * Days + 1227) / DAYSPERQUADRICENTENNIUM) + 3 ) / 4; |
| 147 | Days += 28188 + cleaps; |
| 148 | years = (20 * Days - 2442) / (5 * DAYSPERNORMALQUADRENNIUM); |
| 149 | yearday = Days - (years * DAYSPERNORMALQUADRENNIUM)/4; |
| 150 | months = (64 * yearday) / 1959; |
| 151 | /* the result is based on a year starting on March. |
| 152 | * To convert take 12 from Januari and Februari and |
| 153 | * increase the year by one. */ |
| 154 | if( months < 14 ) { |
| 155 | TimeFields->Month = months - 1; |
| 156 | TimeFields->Year = years + 1524; |
| 157 | } else { |
| 158 | TimeFields->Month = months - 13; |
| 159 | TimeFields->Year = years + 1525; |
| 160 | } |
| 161 | /* calculation of day of month is based on the wonderful |
| 162 | * sequence of INT( n * 30.6): it reproduces the |
| 163 | * 31-30-31-30-31-31 month lengths exactly for small n's */ |
| 164 | TimeFields->Day = yearday - (1959 * months) / 64 ; |
| 165 | return; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 166 | } |
György 'Nog' Jeney | 39433b9 | 2002-11-06 21:57:23 +0000 | [diff] [blame] | 167 | |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 168 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 169 | * RtlTimeFieldsToTime [NTDLL.@] |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 170 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 171 | * Convert a TIME_FIELDS structure into a time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 172 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 173 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 174 | * ftTimeFields [I] TIME_FIELDS structure to convert. |
| 175 | * Time [O] Destination for the converted time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 176 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 177 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 178 | * Success: TRUE. |
| 179 | * Failure: FALSE. |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 180 | */ |
| 181 | BOOLEAN WINAPI RtlTimeFieldsToTime( |
| 182 | PTIME_FIELDS tfTimeFields, |
| 183 | PLARGE_INTEGER Time) |
| 184 | { |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 185 | int month, year, cleaps, day; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 186 | |
| 187 | /* FIXME: normalize the TIME_FIELDS structure here */ |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 188 | /* No, native just returns 0 (error) if the fields are not */ |
| 189 | if( tfTimeFields->Milliseconds< 0 || tfTimeFields->Milliseconds > 999 || |
| 190 | tfTimeFields->Second < 0 || tfTimeFields->Second > 59 || |
| 191 | tfTimeFields->Minute < 0 || tfTimeFields->Minute > 59 || |
| 192 | tfTimeFields->Hour < 0 || tfTimeFields->Hour > 23 || |
| 193 | tfTimeFields->Month < 1 || tfTimeFields->Month > 12 || |
| 194 | tfTimeFields->Day < 1 || |
| 195 | tfTimeFields->Day > MonthLengths |
| 196 | [ tfTimeFields->Month ==2 || IsLeapYear(tfTimeFields->Year)] |
| 197 | [ tfTimeFields->Month - 1] || |
| 198 | tfTimeFields->Year < 1601 ) |
| 199 | return FALSE; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 200 | |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 201 | /* now calculate a day count from the date |
| 202 | * First start counting years from March. This way the leap days |
| 203 | * are added at the end of the year, not somewhere in the middle. |
| 204 | * Formula's become so much less complicate that way. |
| 205 | * To convert: add 12 to the month numbers of Jan and Feb, and |
| 206 | * take 1 from the year */ |
| 207 | if(tfTimeFields->Month < 3) { |
| 208 | month = tfTimeFields->Month + 13; |
| 209 | year = tfTimeFields->Year - 1; |
| 210 | } else { |
| 211 | month = tfTimeFields->Month + 1; |
| 212 | year = tfTimeFields->Year; |
| 213 | } |
| 214 | cleaps = (3 * (year / 100) + 3) / 4; /* nr of "century leap years"*/ |
| 215 | day = (36525 * year) / 100 - cleaps + /* year * dayperyr, corrected */ |
| 216 | (1959 * month) / 64 + /* months * daypermonth */ |
| 217 | tfTimeFields->Day - /* day of the month */ |
| 218 | 584817 ; /* zero that on 1601-01-01 */ |
| 219 | /* done */ |
| 220 | |
| 221 | Time->QuadPart = (((((LONGLONG) day * HOURSPERDAY + |
| 222 | tfTimeFields->Hour) * MINSPERHOUR + |
| 223 | tfTimeFields->Minute) * SECSPERMIN + |
| 224 | tfTimeFields->Second ) * 1000 + |
| 225 | tfTimeFields->Milliseconds ) * TICKSPERMSEC; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 226 | |
Rein Klazes | dceae02 | 2004-11-06 03:53:53 +0000 | [diff] [blame] | 227 | return TRUE; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 228 | } |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 229 | |
Huw Davies | 64ed848 | 2004-02-26 05:26:34 +0000 | [diff] [blame] | 230 | /*********************************************************************** |
| 231 | * TIME_GetBias [internal] |
| 232 | * |
| 233 | * Helper function calculates delta local time from UTC. |
| 234 | * |
| 235 | * PARAMS |
| 236 | * utc [I] The current utc time. |
| 237 | * pdaylight [I] Local daylight. |
| 238 | * |
| 239 | * RETURNS |
| 240 | * The bias for the current timezone. |
| 241 | */ |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 242 | static LONG TIME_GetBias(void) |
Huw Davies | 64ed848 | 2004-02-26 05:26:34 +0000 | [diff] [blame] | 243 | { |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 244 | static time_t last_utc; |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 245 | static LONG last_bias; |
| 246 | LONG ret; |
| 247 | time_t utc; |
| 248 | |
| 249 | utc = time( NULL ); |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 250 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 251 | RtlEnterCriticalSection( &TIME_tz_section ); |
Dmitry Timoshkov | 6119f49 | 2007-07-29 21:33:23 +0900 | [diff] [blame] | 252 | if (utc != last_utc) |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 253 | { |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 254 | RTL_TIME_ZONE_INFORMATION tzi; |
| 255 | int is_dst = init_tz_info( &tzi ); |
| 256 | |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 257 | last_utc = utc; |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 258 | last_bias = tzi.Bias; |
| 259 | last_bias += is_dst ? tzi.DaylightBias : tzi.StandardBias; |
| 260 | last_bias *= SECSPERMIN; |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 261 | } |
Dmitry Timoshkov | 6119f49 | 2007-07-29 21:33:23 +0900 | [diff] [blame] | 262 | |
Dmitry Timoshkov | 6119f49 | 2007-07-29 21:33:23 +0900 | [diff] [blame] | 263 | ret = last_bias; |
| 264 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 265 | RtlLeaveCriticalSection( &TIME_tz_section ); |
Huw Davies | 67e2d6c | 2004-02-27 00:43:20 +0000 | [diff] [blame] | 266 | return ret; |
Huw Davies | 64ed848 | 2004-02-26 05:26:34 +0000 | [diff] [blame] | 267 | } |
| 268 | |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 269 | /****************************************************************************** |
| 270 | * RtlLocalTimeToSystemTime [NTDLL.@] |
| 271 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 272 | * Convert a local time into system time. |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 273 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 274 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 275 | * LocalTime [I] Local time to convert. |
| 276 | * SystemTime [O] Destination for the converted time. |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 277 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 278 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 279 | * Success: STATUS_SUCCESS. |
| 280 | * Failure: An NTSTATUS error code indicating the problem. |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 281 | */ |
| 282 | NTSTATUS WINAPI RtlLocalTimeToSystemTime( const LARGE_INTEGER *LocalTime, |
| 283 | PLARGE_INTEGER SystemTime) |
| 284 | { |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 285 | LONG bias; |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 286 | |
| 287 | TRACE("(%p, %p)\n", LocalTime, SystemTime); |
| 288 | |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 289 | bias = TIME_GetBias(); |
| 290 | SystemTime->QuadPart = LocalTime->QuadPart + bias * (LONGLONG)TICKSPERSEC; |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 291 | return STATUS_SUCCESS; |
| 292 | } |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 293 | |
| 294 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 295 | * RtlSystemTimeToLocalTime [NTDLL.@] |
| 296 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 297 | * Convert a system time into a local time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 298 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 299 | * PARAMS |
| 300 | * SystemTime [I] System time to convert. |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 301 | * LocalTime [O] Destination for the converted time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 302 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 303 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 304 | * Success: STATUS_SUCCESS. |
| 305 | * Failure: An NTSTATUS error code indicating the problem. |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 306 | */ |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 307 | NTSTATUS WINAPI RtlSystemTimeToLocalTime( const LARGE_INTEGER *SystemTime, |
| 308 | PLARGE_INTEGER LocalTime ) |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 309 | { |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 310 | LONG bias; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 311 | |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 312 | TRACE("(%p, %p)\n", SystemTime, LocalTime); |
| 313 | |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 314 | bias = TIME_GetBias(); |
| 315 | LocalTime->QuadPart = SystemTime->QuadPart - bias * (LONGLONG)TICKSPERSEC; |
György 'Nog' Jeney | 4d6ba25 | 2002-12-11 00:19:56 +0000 | [diff] [blame] | 316 | return STATUS_SUCCESS; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 317 | } |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 318 | |
| 319 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 320 | * RtlTimeToSecondsSince1970 [NTDLL.@] |
| 321 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 322 | * Convert a time into a count of seconds since 1970. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 323 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 324 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 325 | * Time [I] Time to convert. |
| 326 | * Seconds [O] Destination for the converted time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 327 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 328 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 329 | * Success: TRUE. |
| 330 | * Failure: FALSE, if the resulting value will not fit in a DWORD. |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 331 | */ |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 332 | BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, LPDWORD Seconds ) |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 333 | { |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 334 | ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart; |
Alexandre Julliard | 4964374 | 2009-08-24 12:50:11 +0200 | [diff] [blame] | 335 | tmp = tmp / TICKSPERSEC - SECS_1601_TO_1970; |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 336 | if (tmp > 0xffffffff) return FALSE; |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 337 | *Seconds = (DWORD)tmp; |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 338 | return TRUE; |
| 339 | } |
| 340 | |
| 341 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 342 | * RtlTimeToSecondsSince1980 [NTDLL.@] |
| 343 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 344 | * Convert a time into a count of seconds since 1980. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 345 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 346 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 347 | * Time [I] Time to convert. |
| 348 | * Seconds [O] Destination for the converted time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 349 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 350 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 351 | * Success: TRUE. |
| 352 | * Failure: FALSE, if the resulting value will not fit in a DWORD. |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 353 | */ |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 354 | BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *Time, LPDWORD Seconds ) |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 355 | { |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 356 | ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart; |
Alexandre Julliard | 4964374 | 2009-08-24 12:50:11 +0200 | [diff] [blame] | 357 | tmp = tmp / TICKSPERSEC - SECS_1601_TO_1980; |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 358 | if (tmp > 0xffffffff) return FALSE; |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 359 | *Seconds = (DWORD)tmp; |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 360 | return TRUE; |
| 361 | } |
| 362 | |
| 363 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 364 | * RtlSecondsSince1970ToTime [NTDLL.@] |
| 365 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 366 | * Convert a count of seconds since 1970 to a time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 367 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 368 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 369 | * Seconds [I] Time to convert. |
| 370 | * Time [O] Destination for the converted time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 371 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 372 | * RETURNS |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 373 | * Nothing. |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 374 | */ |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 375 | void WINAPI RtlSecondsSince1970ToTime( DWORD Seconds, LARGE_INTEGER *Time ) |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 376 | { |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 377 | ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 378 | Time->u.LowPart = (DWORD)secs; |
| 379 | Time->u.HighPart = (DWORD)(secs >> 32); |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 380 | } |
| 381 | |
| 382 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 383 | * RtlSecondsSince1980ToTime [NTDLL.@] |
| 384 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 385 | * Convert a count of seconds since 1980 to a time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 386 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 387 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 388 | * Seconds [I] Time to convert. |
| 389 | * Time [O] Destination for the converted time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 390 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 391 | * RETURNS |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 392 | * Nothing. |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 393 | */ |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 394 | void WINAPI RtlSecondsSince1980ToTime( DWORD Seconds, LARGE_INTEGER *Time ) |
Alexandre Julliard | 0aa6cc2 | 2000-07-29 21:56:59 +0000 | [diff] [blame] | 395 | { |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 396 | ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1980; |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 397 | Time->u.LowPart = (DWORD)secs; |
| 398 | Time->u.HighPart = (DWORD)(secs >> 32); |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 399 | } |
| 400 | |
| 401 | /****************************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 402 | * RtlTimeToElapsedTimeFields [NTDLL.@] |
| 403 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 404 | * Convert a time to a count of elapsed seconds. |
| 405 | * |
| 406 | * PARAMS |
| 407 | * Time [I] Time to convert. |
| 408 | * TimeFields [O] Destination for the converted time. |
| 409 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 410 | * RETURNS |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 411 | * Nothing. |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 412 | */ |
Alexandre Julliard | a16ed90 | 2002-12-18 02:31:33 +0000 | [diff] [blame] | 413 | void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS TimeFields ) |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 414 | { |
Alexandre Julliard | a16ed90 | 2002-12-18 02:31:33 +0000 | [diff] [blame] | 415 | LONGLONG time; |
Mike McCormack | b5bd4a1 | 2005-09-02 14:47:36 +0000 | [diff] [blame] | 416 | INT rem; |
Alexandre Julliard | a16ed90 | 2002-12-18 02:31:33 +0000 | [diff] [blame] | 417 | |
Alexandre Julliard | 4964374 | 2009-08-24 12:50:11 +0200 | [diff] [blame] | 418 | time = Time->QuadPart / TICKSPERSEC; |
| 419 | TimeFields->Milliseconds = (Time->QuadPart % TICKSPERSEC) / TICKSPERMSEC; |
Alexandre Julliard | a16ed90 | 2002-12-18 02:31:33 +0000 | [diff] [blame] | 420 | |
| 421 | /* time is now in seconds */ |
| 422 | TimeFields->Year = 0; |
| 423 | TimeFields->Month = 0; |
Alexandre Julliard | 4964374 | 2009-08-24 12:50:11 +0200 | [diff] [blame] | 424 | TimeFields->Day = time / SECSPERDAY; |
Alexandre Julliard | a16ed90 | 2002-12-18 02:31:33 +0000 | [diff] [blame] | 425 | |
| 426 | /* rem is now the remaining seconds in the last day */ |
Alexandre Julliard | 4964374 | 2009-08-24 12:50:11 +0200 | [diff] [blame] | 427 | rem = time % SECSPERDAY; |
Alexandre Julliard | a16ed90 | 2002-12-18 02:31:33 +0000 | [diff] [blame] | 428 | TimeFields->Second = rem % 60; |
| 429 | rem /= 60; |
| 430 | TimeFields->Minute = rem % 60; |
| 431 | TimeFields->Hour = rem / 60; |
Juergen Schmied | 026d9db | 1999-03-09 17:47:51 +0000 | [diff] [blame] | 432 | } |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 433 | |
| 434 | /*********************************************************************** |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 435 | * NtQuerySystemTime [NTDLL.@] |
| 436 | * ZwQuerySystemTime [NTDLL.@] |
| 437 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 438 | * Get the current system time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 439 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 440 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 441 | * Time [O] Destination for the current system time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 442 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 443 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 444 | * Success: STATUS_SUCCESS. |
| 445 | * Failure: An NTSTATUS error code indicating the problem. |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 446 | */ |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 447 | NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time ) |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 448 | { |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 449 | struct timeval now; |
| 450 | |
| 451 | gettimeofday( &now, 0 ); |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 452 | Time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; |
| 453 | Time->QuadPart += now.tv_usec * 10; |
Patrik Stridvall | 9c1de6d | 2002-09-12 22:07:02 +0000 | [diff] [blame] | 454 | return STATUS_SUCCESS; |
Alexandre Julliard | d76f9f9 | 2000-10-01 01:40:42 +0000 | [diff] [blame] | 455 | } |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 456 | |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 457 | /****************************************************************************** |
| 458 | * NtQueryPerformanceCounter [NTDLL.@] |
| 459 | * |
| 460 | * Note: Windows uses a timer clocked at a multiple of 1193182 Hz. There is a |
| 461 | * good number of applications that crash when the returned frequency is either |
Francois Gouget | ebadbd4 | 2007-08-09 10:42:59 +0200 | [diff] [blame] | 462 | * lower or higher than what Windows gives. Also too high counter values are |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 463 | * reported to give problems. |
| 464 | */ |
| 465 | NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency ) |
| 466 | { |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 467 | LARGE_INTEGER now; |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 468 | |
| 469 | if (!Counter) return STATUS_ACCESS_VIOLATION; |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 470 | |
| 471 | /* convert a counter that increments at a rate of 10 MHz |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 472 | * to one of 1.193182 MHz, with some care for arithmetic |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 473 | * overflow and good accuracy (21/176 = 0.11931818) */ |
| 474 | NtQuerySystemTime( &now ); |
| 475 | Counter->QuadPart = ((now.QuadPart - server_start_time) * 21) / 176; |
Alexandre Julliard | 9ad5628 | 2005-07-14 10:32:46 +0000 | [diff] [blame] | 476 | if (Frequency) Frequency->QuadPart = 1193182; |
| 477 | return STATUS_SUCCESS; |
| 478 | } |
| 479 | |
Jacek Caban | 2333c80 | 2006-04-19 21:21:52 +0200 | [diff] [blame] | 480 | |
| 481 | /****************************************************************************** |
| 482 | * NtGetTickCount (NTDLL.@) |
| 483 | * ZwGetTickCount (NTDLL.@) |
| 484 | */ |
| 485 | ULONG WINAPI NtGetTickCount(void) |
| 486 | { |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 487 | LARGE_INTEGER now; |
Jacek Caban | 2333c80 | 2006-04-19 21:21:52 +0200 | [diff] [blame] | 488 | |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 489 | NtQuerySystemTime( &now ); |
| 490 | return (now.QuadPart - server_start_time) / 10000; |
Jacek Caban | 2333c80 | 2006-04-19 21:21:52 +0200 | [diff] [blame] | 491 | } |
| 492 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 493 | /* calculate the mday of dst change date, so that for instance Sun 5 Oct 2007 |
| 494 | * (last Sunday in October of 2007) becomes Sun Oct 28 2007 |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 495 | * |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 496 | * Note: year, day and month must be in unix format. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 497 | */ |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 498 | static int weekday_to_mday(int year, int day, int mon, int day_of_week) |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 499 | { |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 500 | struct tm date; |
| 501 | time_t tmp; |
| 502 | int wday, mday; |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 503 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 504 | /* find first day in the month matching week day of the date */ |
| 505 | memset(&date, 0, sizeof(date)); |
| 506 | date.tm_year = year; |
| 507 | date.tm_mon = mon; |
| 508 | date.tm_mday = -1; |
| 509 | date.tm_wday = -1; |
| 510 | do |
| 511 | { |
| 512 | date.tm_mday++; |
| 513 | tmp = mktime(&date); |
| 514 | } while (date.tm_wday != day_of_week || date.tm_mon != mon); |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 515 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 516 | mday = date.tm_mday; |
| 517 | |
| 518 | /* find number of week days in the month matching week day of the date */ |
| 519 | wday = 1; /* 1 - 1st, ...., 5 - last */ |
| 520 | while (wday < day) |
| 521 | { |
| 522 | struct tm *tm; |
| 523 | |
| 524 | date.tm_mday += 7; |
| 525 | tmp = mktime(&date); |
| 526 | tm = localtime(&tmp); |
| 527 | if (tm->tm_mon != mon) |
| 528 | break; |
| 529 | mday = tm->tm_mday; |
| 530 | wday++; |
| 531 | } |
| 532 | |
| 533 | return mday; |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 534 | } |
| 535 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 536 | static BOOL match_tz_date(const RTL_SYSTEM_TIME *st, const RTL_SYSTEM_TIME *reg_st) |
Rein Klazes | c5c93d1 | 2004-10-18 21:19:28 +0000 | [diff] [blame] | 537 | { |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 538 | WORD wDay; |
| 539 | |
| 540 | if (st->wMonth != reg_st->wMonth) return FALSE; |
| 541 | |
| 542 | if (!st->wMonth) return TRUE; /* no transition dates */ |
| 543 | |
| 544 | wDay = reg_st->wDay; |
| 545 | if (!reg_st->wYear) /* date in a day-of-week format */ |
| 546 | wDay = weekday_to_mday(st->wYear - 1900, reg_st->wDay, reg_st->wMonth - 1, reg_st->wDayOfWeek); |
| 547 | |
| 548 | if (st->wDay != wDay || |
| 549 | st->wHour != reg_st->wHour || |
| 550 | st->wMinute != reg_st->wMinute || |
| 551 | st->wSecond != reg_st->wSecond || |
| 552 | st->wMilliseconds != reg_st->wMilliseconds) return FALSE; |
| 553 | |
| 554 | return TRUE; |
| 555 | } |
| 556 | |
| 557 | static BOOL match_tz_info(const RTL_TIME_ZONE_INFORMATION *tzi, const RTL_TIME_ZONE_INFORMATION *reg_tzi) |
| 558 | { |
| 559 | if (tzi->Bias == reg_tzi->Bias && |
| 560 | match_tz_date(&tzi->StandardDate, ®_tzi->StandardDate) && |
| 561 | match_tz_date(&tzi->DaylightDate, ®_tzi->DaylightDate)) |
| 562 | return TRUE; |
| 563 | |
| 564 | return FALSE; |
| 565 | } |
| 566 | |
| 567 | static BOOL reg_query_value(HKEY hkey, LPCWSTR name, DWORD type, void *data, DWORD count) |
| 568 | { |
| 569 | UNICODE_STRING nameW; |
| 570 | char buf[256]; |
| 571 | KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buf; |
| 572 | |
| 573 | if (count > sizeof(buf) - sizeof(KEY_VALUE_PARTIAL_INFORMATION)) |
| 574 | return FALSE; |
| 575 | |
| 576 | RtlInitUnicodeString(&nameW, name); |
| 577 | |
| 578 | if (NtQueryValueKey(hkey, &nameW, KeyValuePartialInformation, |
| 579 | buf, sizeof(buf), &count)) |
| 580 | return FALSE; |
| 581 | |
| 582 | if (info->Type != type) return FALSE; |
| 583 | |
| 584 | memcpy(data, info->Data, info->DataLength); |
| 585 | return TRUE; |
| 586 | } |
| 587 | |
| 588 | static void find_reg_tz_info(RTL_TIME_ZONE_INFORMATION *tzi) |
| 589 | { |
| 590 | static const WCHAR Time_ZonesW[] = { 'M','a','c','h','i','n','e','\\', |
| 591 | 'S','o','f','t','w','a','r','e','\\', |
| 592 | 'M','i','c','r','o','s','o','f','t','\\', |
| 593 | 'W','i','n','d','o','w','s',' ','N','T','\\', |
| 594 | 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', |
| 595 | 'T','i','m','e',' ','Z','o','n','e','s',0 }; |
Mike McCormack | 5b2d5fd | 2005-06-17 13:58:33 +0000 | [diff] [blame] | 596 | HANDLE hkey; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 597 | ULONG idx; |
Rein Klazes | c5c93d1 | 2004-10-18 21:19:28 +0000 | [diff] [blame] | 598 | OBJECT_ATTRIBUTES attr; |
| 599 | UNICODE_STRING nameW; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 600 | WCHAR buf[128]; |
Rein Klazes | c5c93d1 | 2004-10-18 21:19:28 +0000 | [diff] [blame] | 601 | |
| 602 | attr.Length = sizeof(attr); |
| 603 | attr.RootDirectory = 0; |
| 604 | attr.ObjectName = &nameW; |
| 605 | attr.Attributes = 0; |
| 606 | attr.SecurityDescriptor = NULL; |
| 607 | attr.SecurityQualityOfService = NULL; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 608 | RtlInitUnicodeString(&nameW, Time_ZonesW); |
| 609 | if (NtOpenKey(&hkey, KEY_READ, &attr)) |
| 610 | { |
| 611 | WARN("Unable to open the time zones key\n"); |
| 612 | return; |
Rein Klazes | c5c93d1 | 2004-10-18 21:19:28 +0000 | [diff] [blame] | 613 | } |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 614 | |
| 615 | idx = 0; |
| 616 | nameW.Buffer = buf; |
| 617 | nameW.Length = sizeof(buf); |
| 618 | nameW.MaximumLength = sizeof(buf); |
| 619 | |
| 620 | while (!RtlpNtEnumerateSubKey(hkey, &nameW, idx++)) |
| 621 | { |
| 622 | static const WCHAR stdW[] = { 'S','t','d',0 }; |
| 623 | static const WCHAR dltW[] = { 'D','l','t',0 }; |
| 624 | static const WCHAR tziW[] = { 'T','Z','I',0 }; |
| 625 | RTL_TIME_ZONE_INFORMATION reg_tzi; |
| 626 | HANDLE hSubkey; |
| 627 | struct tz_reg_data |
| 628 | { |
| 629 | LONG bias; |
| 630 | LONG std_bias; |
| 631 | LONG dlt_bias; |
| 632 | RTL_SYSTEM_TIME std_date; |
| 633 | RTL_SYSTEM_TIME dlt_date; |
| 634 | } tz_data; |
| 635 | |
| 636 | attr.Length = sizeof(attr); |
| 637 | attr.RootDirectory = hkey; |
| 638 | attr.ObjectName = &nameW; |
| 639 | attr.Attributes = 0; |
| 640 | attr.SecurityDescriptor = NULL; |
| 641 | attr.SecurityQualityOfService = NULL; |
| 642 | if (NtOpenKey(&hSubkey, KEY_READ, &attr)) |
| 643 | { |
| 644 | WARN("Unable to open subkey %s\n", debugstr_wn(nameW.Buffer, nameW.Length/sizeof(WCHAR))); |
| 645 | continue; |
| 646 | } |
| 647 | |
| 648 | #define get_value(hkey, name, type, data, len) \ |
| 649 | if (!reg_query_value(hkey, name, type, data, len)) \ |
| 650 | { \ |
| 651 | WARN("can't read data from %s\n", debugstr_w(name)); \ |
| 652 | NtClose(hkey); \ |
| 653 | continue; \ |
| 654 | } |
| 655 | |
| 656 | get_value(hSubkey, stdW, REG_SZ, reg_tzi.StandardName, sizeof(reg_tzi.StandardName)); |
| 657 | get_value(hSubkey, dltW, REG_SZ, reg_tzi.DaylightName, sizeof(reg_tzi.DaylightName)); |
| 658 | get_value(hSubkey, tziW, REG_BINARY, &tz_data, sizeof(tz_data)); |
| 659 | |
| 660 | #undef get_value |
| 661 | |
| 662 | reg_tzi.Bias = tz_data.bias; |
| 663 | reg_tzi.StandardBias = tz_data.std_bias; |
| 664 | reg_tzi.DaylightBias = tz_data.dlt_bias; |
| 665 | reg_tzi.StandardDate = tz_data.std_date; |
| 666 | reg_tzi.DaylightDate = tz_data.dlt_date; |
| 667 | |
| 668 | TRACE("%s: bias %d\n", debugstr_wn(nameW.Buffer, nameW.Length/sizeof(WCHAR)), reg_tzi.Bias); |
| 669 | TRACE("std (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", |
| 670 | reg_tzi.StandardDate.wDay, reg_tzi.StandardDate.wMonth, |
| 671 | reg_tzi.StandardDate.wYear, reg_tzi.StandardDate.wDayOfWeek, |
| 672 | reg_tzi.StandardDate.wHour, reg_tzi.StandardDate.wMinute, |
| 673 | reg_tzi.StandardDate.wSecond, reg_tzi.StandardDate.wMilliseconds, |
| 674 | reg_tzi.StandardBias); |
| 675 | TRACE("dst (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", |
| 676 | reg_tzi.DaylightDate.wDay, reg_tzi.DaylightDate.wMonth, |
| 677 | reg_tzi.DaylightDate.wYear, reg_tzi.DaylightDate.wDayOfWeek, |
| 678 | reg_tzi.DaylightDate.wHour, reg_tzi.DaylightDate.wMinute, |
| 679 | reg_tzi.DaylightDate.wSecond, reg_tzi.DaylightDate.wMilliseconds, |
| 680 | reg_tzi.DaylightBias); |
| 681 | |
| 682 | NtClose(hSubkey); |
| 683 | |
| 684 | if (match_tz_info(tzi, ®_tzi)) |
| 685 | { |
Andrew Talbot | 5ecd33e | 2008-03-08 15:37:05 +0000 | [diff] [blame] | 686 | *tzi = reg_tzi; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 687 | NtClose(hkey); |
| 688 | return; |
| 689 | } |
| 690 | |
| 691 | /* reset len */ |
| 692 | nameW.Length = sizeof(buf); |
| 693 | nameW.MaximumLength = sizeof(buf); |
| 694 | } |
| 695 | |
| 696 | NtClose(hkey); |
| 697 | |
| 698 | FIXME("Can't find matching timezone information in the registry for " |
| 699 | "bias %d, std (d/m/y): %u/%02u/%04u, dlt (d/m/y): %u/%02u/%04u\n", |
| 700 | tzi->Bias, |
| 701 | tzi->StandardDate.wDay, tzi->StandardDate.wMonth, tzi->StandardDate.wYear, |
| 702 | tzi->DaylightDate.wDay, tzi->DaylightDate.wMonth, tzi->DaylightDate.wYear); |
| 703 | } |
| 704 | |
| 705 | static time_t find_dst_change(unsigned long min, unsigned long max, int *is_dst) |
| 706 | { |
| 707 | time_t start; |
| 708 | struct tm *tm; |
| 709 | |
| 710 | start = min; |
| 711 | tm = localtime(&start); |
| 712 | *is_dst = !tm->tm_isdst; |
| 713 | TRACE("starting date isdst %d, %s", !*is_dst, ctime(&start)); |
| 714 | |
| 715 | while (min <= max) |
| 716 | { |
| 717 | time_t pos = (min + max) / 2; |
| 718 | tm = localtime(&pos); |
| 719 | |
| 720 | if (tm->tm_isdst != *is_dst) |
| 721 | min = pos + 1; |
| 722 | else |
| 723 | max = pos - 1; |
| 724 | } |
| 725 | return min; |
| 726 | } |
| 727 | |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 728 | static int init_tz_info(RTL_TIME_ZONE_INFORMATION *tzi) |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 729 | { |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 730 | static RTL_TIME_ZONE_INFORMATION cached_tzi; |
Dmitry Timoshkov | 0e44bda | 2011-10-18 15:34:05 +0900 | [diff] [blame] | 731 | static int current_year = -1, current_bias = 65535; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 732 | struct tm *tm; |
| 733 | time_t year_start, year_end, tmp, dlt = 0, std = 0; |
Dmitry Timoshkov | 0e44bda | 2011-10-18 15:34:05 +0900 | [diff] [blame] | 734 | int is_dst, current_is_dst, bias; |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 735 | |
| 736 | RtlEnterCriticalSection( &TIME_tz_section ); |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 737 | |
| 738 | year_start = time(NULL); |
Dmitry Timoshkov | 0e44bda | 2011-10-18 15:34:05 +0900 | [diff] [blame] | 739 | tm = gmtime(&year_start); |
| 740 | bias = (LONG)(mktime(tm) - year_start) / 60; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 741 | |
Dmitry Timoshkov | 0e44bda | 2011-10-18 15:34:05 +0900 | [diff] [blame] | 742 | tm = localtime(&year_start); |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 743 | current_is_dst = tm->tm_isdst; |
Dmitry Timoshkov | 0e44bda | 2011-10-18 15:34:05 +0900 | [diff] [blame] | 744 | if (current_year == tm->tm_year && current_bias == bias) |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 745 | { |
| 746 | *tzi = cached_tzi; |
| 747 | RtlLeaveCriticalSection( &TIME_tz_section ); |
| 748 | return current_is_dst; |
| 749 | } |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 750 | |
| 751 | memset(tzi, 0, sizeof(*tzi)); |
| 752 | |
Dmitry Timoshkov | 0e44bda | 2011-10-18 15:34:05 +0900 | [diff] [blame] | 753 | TRACE("tz data will be valid through year %d, bias %d\n", tm->tm_year + 1900, bias); |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 754 | current_year = tm->tm_year; |
Dmitry Timoshkov | 0e44bda | 2011-10-18 15:34:05 +0900 | [diff] [blame] | 755 | current_bias = bias; |
| 756 | |
| 757 | tzi->Bias = bias; |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 758 | |
| 759 | tm->tm_isdst = 0; |
| 760 | tm->tm_mday = 1; |
| 761 | tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = tm->tm_wday = tm->tm_yday = 0; |
| 762 | year_start = mktime(tm); |
| 763 | TRACE("year_start: %s", ctime(&year_start)); |
| 764 | |
| 765 | tm->tm_mday = tm->tm_wday = tm->tm_yday = 0; |
| 766 | tm->tm_mon = 12; |
| 767 | tm->tm_hour = 23; |
| 768 | tm->tm_min = tm->tm_sec = 59; |
| 769 | year_end = mktime(tm); |
| 770 | TRACE("year_end: %s", ctime(&year_end)); |
| 771 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 772 | tmp = find_dst_change(year_start, year_end, &is_dst); |
| 773 | if (is_dst) |
| 774 | dlt = tmp; |
| 775 | else |
| 776 | std = tmp; |
| 777 | |
| 778 | tmp = find_dst_change(tmp, year_end, &is_dst); |
| 779 | if (is_dst) |
| 780 | dlt = tmp; |
| 781 | else |
| 782 | std = tmp; |
| 783 | |
| 784 | TRACE("std: %s", ctime(&std)); |
| 785 | TRACE("dlt: %s", ctime(&dlt)); |
| 786 | |
| 787 | if (dlt == std || !dlt || !std) |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 788 | TRACE("there is no daylight saving rules in this time zone\n"); |
Dmitry Timoshkov | a76ef05 | 2007-08-29 18:56:52 +0900 | [diff] [blame] | 789 | else |
| 790 | { |
| 791 | tmp = dlt - tzi->Bias * 60; |
| 792 | tm = gmtime(&tmp); |
| 793 | TRACE("dlt gmtime: %s", asctime(tm)); |
| 794 | |
| 795 | tzi->DaylightBias = -60; |
| 796 | tzi->DaylightDate.wYear = tm->tm_year + 1900; |
| 797 | tzi->DaylightDate.wMonth = tm->tm_mon + 1; |
| 798 | tzi->DaylightDate.wDayOfWeek = tm->tm_wday; |
| 799 | tzi->DaylightDate.wDay = tm->tm_mday; |
| 800 | tzi->DaylightDate.wHour = tm->tm_hour; |
| 801 | tzi->DaylightDate.wMinute = tm->tm_min; |
| 802 | tzi->DaylightDate.wSecond = tm->tm_sec; |
| 803 | tzi->DaylightDate.wMilliseconds = 0; |
| 804 | |
| 805 | TRACE("daylight (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", |
| 806 | tzi->DaylightDate.wDay, tzi->DaylightDate.wMonth, |
| 807 | tzi->DaylightDate.wYear, tzi->DaylightDate.wDayOfWeek, |
| 808 | tzi->DaylightDate.wHour, tzi->DaylightDate.wMinute, |
| 809 | tzi->DaylightDate.wSecond, tzi->DaylightDate.wMilliseconds, |
| 810 | tzi->DaylightBias); |
| 811 | |
| 812 | tmp = std - tzi->Bias * 60 - tzi->DaylightBias * 60; |
| 813 | tm = gmtime(&tmp); |
| 814 | TRACE("std gmtime: %s", asctime(tm)); |
| 815 | |
| 816 | tzi->StandardBias = 0; |
| 817 | tzi->StandardDate.wYear = tm->tm_year + 1900; |
| 818 | tzi->StandardDate.wMonth = tm->tm_mon + 1; |
| 819 | tzi->StandardDate.wDayOfWeek = tm->tm_wday; |
| 820 | tzi->StandardDate.wDay = tm->tm_mday; |
| 821 | tzi->StandardDate.wHour = tm->tm_hour; |
| 822 | tzi->StandardDate.wMinute = tm->tm_min; |
| 823 | tzi->StandardDate.wSecond = tm->tm_sec; |
| 824 | tzi->StandardDate.wMilliseconds = 0; |
| 825 | |
| 826 | TRACE("standard (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", |
| 827 | tzi->StandardDate.wDay, tzi->StandardDate.wMonth, |
| 828 | tzi->StandardDate.wYear, tzi->StandardDate.wDayOfWeek, |
| 829 | tzi->StandardDate.wHour, tzi->StandardDate.wMinute, |
| 830 | tzi->StandardDate.wSecond, tzi->StandardDate.wMilliseconds, |
| 831 | tzi->StandardBias); |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 832 | } |
| 833 | |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 834 | find_reg_tz_info(tzi); |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 835 | cached_tzi = *tzi; |
| 836 | |
| 837 | RtlLeaveCriticalSection( &TIME_tz_section ); |
| 838 | |
| 839 | return current_is_dst; |
Rein Klazes | c5c93d1 | 2004-10-18 21:19:28 +0000 | [diff] [blame] | 840 | } |
| 841 | |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 842 | /*********************************************************************** |
| 843 | * RtlQueryTimeZoneInformation [NTDLL.@] |
| 844 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 845 | * Get information about the current timezone. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 846 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 847 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 848 | * tzinfo [O] Destination for the retrieved timezone info. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 849 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 850 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 851 | * Success: STATUS_SUCCESS. |
| 852 | * Failure: An NTSTATUS error code indicating the problem. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 853 | */ |
Mike McCormack | 78911f3 | 2005-06-20 18:37:17 +0000 | [diff] [blame] | 854 | NTSTATUS WINAPI RtlQueryTimeZoneInformation(RTL_TIME_ZONE_INFORMATION *tzinfo) |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 855 | { |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 856 | init_tz_info( tzinfo ); |
Dmitry Timoshkov | d666143 | 2007-08-07 20:01:16 +0900 | [diff] [blame] | 857 | |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 858 | return STATUS_SUCCESS; |
| 859 | } |
| 860 | |
| 861 | /*********************************************************************** |
| 862 | * RtlSetTimeZoneInformation [NTDLL.@] |
| 863 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 864 | * Set the current time zone information. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 865 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 866 | * PARAMS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 867 | * tzinfo [I] Timezone information to set. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 868 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 869 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 870 | * Success: STATUS_SUCCESS. |
| 871 | * Failure: An NTSTATUS error code indicating the problem. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 872 | * |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 873 | */ |
Mike McCormack | 78911f3 | 2005-06-20 18:37:17 +0000 | [diff] [blame] | 874 | NTSTATUS WINAPI RtlSetTimeZoneInformation( const RTL_TIME_ZONE_INFORMATION *tzinfo ) |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 875 | { |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 876 | return STATUS_PRIVILEGE_NOT_HELD; |
| 877 | } |
| 878 | |
| 879 | /*********************************************************************** |
| 880 | * NtSetSystemTime [NTDLL.@] |
| 881 | * ZwSetSystemTime [NTDLL.@] |
| 882 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 883 | * Set the system time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 884 | * |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 885 | * PARAMS |
| 886 | * NewTime [I] The time to set. |
| 887 | * OldTime [O] Optional destination for the previous system time. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 888 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 889 | * RETURNS |
Jon Griffiths | 0892285 | 2003-08-19 00:56:34 +0000 | [diff] [blame] | 890 | * Success: STATUS_SUCCESS. |
| 891 | * Failure: An NTSTATUS error code indicating the problem. |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 892 | */ |
| 893 | NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *NewTime, LARGE_INTEGER *OldTime) |
| 894 | { |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 895 | struct timeval tv; |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 896 | time_t tm_t; |
| 897 | DWORD sec, oldsec; |
| 898 | LARGE_INTEGER tm; |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 899 | |
| 900 | /* Return the old time if necessary */ |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 901 | if (!OldTime) OldTime = &tm; |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 902 | |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 903 | NtQuerySystemTime( OldTime ); |
| 904 | RtlTimeToSecondsSince1970( OldTime, &oldsec ); |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 905 | |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 906 | RtlTimeToSecondsSince1970( NewTime, &sec ); |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 907 | |
| 908 | /* set the new time */ |
| 909 | tv.tv_sec = sec; |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 910 | tv.tv_usec = 0; |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 911 | |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 912 | #ifdef HAVE_SETTIMEOFDAY |
Rob Shearman | 67cc030 | 2007-09-07 18:41:42 +0100 | [diff] [blame] | 913 | if (!settimeofday(&tv, NULL)) /* 0 is OK, -1 is error */ |
| 914 | return STATUS_SUCCESS; |
Dmitry Timoshkov | d2d5bbe | 2007-08-22 17:02:18 +0900 | [diff] [blame] | 915 | tm_t = sec; |
Rob Shearman | 67cc030 | 2007-09-07 18:41:42 +0100 | [diff] [blame] | 916 | ERR("Cannot set time to %s, time adjustment %ld: %s\n", |
| 917 | ctime(&tm_t), (long)(sec-oldsec), strerror(errno)); |
| 918 | if (errno == EPERM) |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 919 | return STATUS_PRIVILEGE_NOT_HELD; |
| 920 | else |
Rob Shearman | 67cc030 | 2007-09-07 18:41:42 +0100 | [diff] [blame] | 921 | return STATUS_INVALID_PARAMETER; |
| 922 | #else |
| 923 | tm_t = sec; |
| 924 | FIXME("setting time to %s not implemented for missing settimeofday\n", |
| 925 | ctime(&tm_t)); |
| 926 | return STATUS_NOT_IMPLEMENTED; |
| 927 | #endif |
György 'Nog' Jeney | 6f3015b | 2002-11-25 01:12:39 +0000 | [diff] [blame] | 928 | } |