SetLocalTime() and SetSystemTime() bugfixes. Added a maximum clock
adjustment of 2 minutes just in case...
This commit is contained in:
parent
b2dd2c5cee
commit
14e5252185
86
win32/time.c
86
win32/time.c
|
@ -14,6 +14,20 @@
|
|||
|
||||
DEFAULT_DEBUG_CHANNEL(win32)
|
||||
|
||||
/* maximum time adjustment in seconds for SetLocalTime and SetSystemTime */
|
||||
#define SETTIME_MAX_ADJUST 120
|
||||
|
||||
/* TIME_GetBias: helper function calculates delta local time from UTC */
|
||||
static int TIME_GetBias( time_t utc, int *pdaylight)
|
||||
{
|
||||
struct tm *ptm = localtime(&utc);
|
||||
*pdaylight = ptm->tm_isdst; /* daylight for local timezone */
|
||||
ptm = gmtime(&utc);
|
||||
ptm->tm_isdst = *pdaylight; /* use local daylight, not that of Greenwich */
|
||||
return (int)(utc-mktime(ptm));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetLocalTime (KERNEL32.228)
|
||||
*/
|
||||
|
@ -49,20 +63,39 @@ BOOL WINAPI SetLocalTime(const SYSTEMTIME *systime)
|
|||
struct timeval tv;
|
||||
struct tm t;
|
||||
time_t sec;
|
||||
time_t oldsec=time(NULL);
|
||||
int err;
|
||||
|
||||
/* get the number of seconds */
|
||||
t.tm_sec = systime->wSecond;
|
||||
t.tm_min = systime->wMinute;
|
||||
t.tm_hour = systime->wHour;
|
||||
t.tm_mday = systime->wDay;
|
||||
t.tm_mon = systime->wMonth;
|
||||
t.tm_year = systime->wYear;
|
||||
t.tm_mon = systime->wMonth - 1;
|
||||
t.tm_year = systime->wYear - 1900;
|
||||
t.tm_isdst = -1;
|
||||
sec = mktime (&t);
|
||||
|
||||
/* set the new time */
|
||||
tv.tv_sec = sec;
|
||||
tv.tv_usec = systime->wMilliseconds * 1000;
|
||||
return !settimeofday(&tv, NULL);
|
||||
|
||||
/* error and sanity check*/
|
||||
if( sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST ){
|
||||
err = 1;
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
} else {
|
||||
err=settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
|
||||
if(err == 0)
|
||||
return TRUE;
|
||||
SetLastError(ERROR_PRIVILEGE_NOT_HELD);
|
||||
}
|
||||
ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
|
||||
systime->wYear, systime->wMonth, systime->wDay, systime->wHour,
|
||||
systime->wMinute, systime->wSecond,
|
||||
sec-oldsec, err == -1 ? "No Permission" :
|
||||
sec==(time_t)-1 ? "" : "is too large." );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,24 +131,49 @@ BOOL WINAPI SetSystemTime(const SYSTEMTIME *systime)
|
|||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
struct tm t;
|
||||
time_t sec;
|
||||
time_t sec, oldsec;
|
||||
int dst, bias;
|
||||
int err;
|
||||
|
||||
/* call gettimeofday to get the current timezone */
|
||||
gettimeofday(&tv, &tz);
|
||||
oldsec=tv.tv_sec;
|
||||
/* get delta local time from utc */
|
||||
bias=TIME_GetBias(oldsec,&dst);
|
||||
|
||||
|
||||
/* get the number of seconds */
|
||||
t.tm_sec = systime->wSecond;
|
||||
t.tm_min = systime->wMinute;
|
||||
t.tm_hour = systime->wHour;
|
||||
t.tm_mday = systime->wDay;
|
||||
t.tm_mon = systime->wMonth;
|
||||
t.tm_year = systime->wYear;
|
||||
t.tm_mon = systime->wMonth - 1;
|
||||
t.tm_year = systime->wYear - 1900;
|
||||
t.tm_isdst = dst;
|
||||
sec = mktime (&t);
|
||||
/* correct for timezone and daylight */
|
||||
sec += bias;
|
||||
|
||||
/* set the new time */
|
||||
tv.tv_sec = sec;
|
||||
tv.tv_usec = systime->wMilliseconds * 1000;
|
||||
return !settimeofday(&tv, &tz);
|
||||
|
||||
/* error and sanity check*/
|
||||
if( sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST ){
|
||||
err = 1;
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
} else {
|
||||
err=settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
|
||||
if(err == 0)
|
||||
return TRUE;
|
||||
SetLastError(ERROR_PRIVILEGE_NOT_HELD);
|
||||
}
|
||||
ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
|
||||
systime->wYear, systime->wMonth, systime->wDay, systime->wHour,
|
||||
systime->wMinute, systime->wSecond,
|
||||
sec-oldsec, err == -1 ? "No Permission" :
|
||||
sec==(time_t)-1 ? "" : "is too large." );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -124,21 +182,15 @@ BOOL WINAPI SetSystemTime(const SYSTEMTIME *systime)
|
|||
*/
|
||||
DWORD WINAPI GetTimeZoneInformation(LPTIME_ZONE_INFORMATION tzinfo)
|
||||
{
|
||||
time_t gmt, lt;
|
||||
struct tm *ptm;
|
||||
int daylight;
|
||||
time_t gmt;
|
||||
int bias, daylight;
|
||||
|
||||
memset(tzinfo, 0, sizeof(TIME_ZONE_INFORMATION));
|
||||
|
||||
gmt = time(NULL);
|
||||
ptm=localtime(&gmt);
|
||||
daylight=ptm->tm_isdst;
|
||||
|
||||
ptm = gmtime(&gmt);
|
||||
ptm->tm_isdst=daylight;
|
||||
lt = mktime(ptm);
|
||||
bias=TIME_GetBias(gmt,&daylight);
|
||||
|
||||
tzinfo->Bias = (lt - gmt) / 60;
|
||||
tzinfo->Bias = -bias / 60;
|
||||
tzinfo->StandardBias = 0;
|
||||
tzinfo->DaylightBias = -60;
|
||||
|
||||
|
|
Loading…
Reference in New Issue