From 6f3015b8eed5d4bee699499acb8532a112d99c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gy=C3=B6rgy=20=27Nog=27=20Jeney?= Date: Mon, 25 Nov 2002 01:12:39 +0000 Subject: [PATCH] - Move SetSystemTime, GetTimeZoneInformation and SetTimeZoneInformation implementation to ntdll. - Docu updates. --- dlls/kernel/time.c | 340 ++------------------------- dlls/ntdll/ntdll.spec | 8 +- dlls/ntdll/time.c | 521 ++++++++++++++++++++++++++++++++++++++++-- include/winternl.h | 6 +- 4 files changed, 535 insertions(+), 340 deletions(-) diff --git a/dlls/kernel/time.c b/dlls/kernel/time.c index 8f42779aced..e3231f504f2 100644 --- a/dlls/kernel/time.c +++ b/dlls/kernel/time.c @@ -45,250 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win32); #define CALINFO_MAX_YEAR 2029 -/* This structure is used to store strings that represent all of the time zones - in the world. (This is used to help GetTimeZoneInformation) -*/ -struct tagTZ_INFO -{ - const char *psTZFromUnix; - WCHAR psTZWindows[32]; - int bias; - int dst; -}; - -static const struct tagTZ_INFO TZ_INFO[] = -{ - {"MHT", - {'D','a','t','e','l','i','n','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -720, 0}, - {"SST", - {'S','a','m','o','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 660, 0}, - {"HST", - {'H','a','w','a','i','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 600, 0}, - {"AKDT", - {'A','l','a','s','k','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 480, 1}, - {"PDT", - {'P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 420, 1}, - {"MST", - {'U','S',' ','M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 420, 0}, - {"MDT", - {'M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 360, 1}, - {"CST", - {'C','e','n','t','r','a','l',' ','A','m','e','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 360, 0}, - {"CDT", - {'C','e','n','t','r','a','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 300, 1}, - {"COT", - {'S','A',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 300, 0}, - {"EDT", - {'E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 240, 1}, - {"EST", - {'U','S',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 300, 0}, - {"ADT", - {'A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 180, 1}, - {"VET", - {'S','A',' ','W','e','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 240, 0}, - {"CLT", - {'P','a','c','i','f','i','c',' ','S','A',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 240, 0}, - {"NDT", - {'N','e','w','f','o','u','n','d','l','a','n','d',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 150, 1}, - {"BRT", - {'E','.',' ','S','o','u','t','h',' ','A','m','e','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 180, 0}, - {"ART", - {'S','A',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 180, 0}, - {"WGST", - {'G','r','e','e','n','l','a','n','d',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 120, 1}, - {"GST", - {'M','i','d','-','A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 120, 0}, - {"AZOST", - {'A','z','o','r','e','s',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 0, 1}, - {"CVT", - {'C','a','p','e',' ','V','e','r','d','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 60, 0}, - {"WET", - {'G','r','e','e','n','w','i','c','h',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 0, 0}, - {"BST", - {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -60, 1}, - {"GMT", - {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - 0, 0}, - {"CEST", - {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -120, 1}, - {"WAT", - {'W','.',' ','C','e','n','t','r','a','l',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -60, 0}, - {"EEST", - {'E','.',' ','E','u','r','o','p','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -180, 1}, - {"EET", - {'E','g','y','p','t',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -120, 0}, - {"CAT", - {'S','o','u','t','h',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -120, 0}, - {"IST", - {'I','s','r','a','e','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -120, 0}, - {"ADT", - {'A','r','a','b','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -240, 1}, - {"AST", - {'A','r','a','b',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -180, 0}, - {"MSD", - {'R','u','s','s','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -240, 1}, - {"EAT", - {'E','.',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -180, 0}, - {"IRST", - {'I','r','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -270, 1}, - {"GST", - {'A','r','a','b','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -240, 0}, - {"AZST", - {'C','a','u','c','a','s','u','s',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -300, 1}, - {"AFT", - {'A','f','g','h','a','n','i','s','t','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -270, 0}, - {"YEKST", - {'E','k','a','t','e','r','i','n','b','u','r','g',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -360, 1}, - {"PKT", - {'W','e','s','t',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -300, 0}, - {"IST", - {'I','n','d','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -330, 0}, - {"NPT", - {'N','e','p','a','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -345, 0}, - {"ALMST", - {'N','.',' ','C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -420, 1}, - {"BDT", - {'C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -360, 0}, - {"LKT", - {'S','r','i',' ','L','a','n','k','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -360, 0}, - {"MMT", - {'M','y','a','n','m','a','r',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -390, 0}, - {"ICT", - {'S','E',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -420, 0}, - {"KRAST", - {'N','o','r','t','h',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -480, 1}, - {"CST", - {'C','h','i','n','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -480, 0}, - {"IRKST", - {'N','o','r','t','h',' ','A','s','i','a',' ','E','a','s','t',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -540, 1}, - {"SGT", - {'M','a','l','a','y',' ','P','e','n','i','n','s','u','l','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -480, 0}, - {"WST", - {'W','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -480, 0}, - {"JST", - {'T','o','k','y','o',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -540, 0}, - {"KST", - {'K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -540, 0}, - {"YAKST", - {'Y','a','k','u','t','s','k',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -600, 1}, - {"CST", - {'C','e','n','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -570, 0}, - {"EST", - {'E','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -600, 0}, - {"GST", - {'W','e','s','t',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -600, 0}, - {"VLAST", - {'V','l','a','d','i','v','o','s','t','o','k',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -660, 1}, - {"MAGST", - {'C','e','n','t','r','a','l',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -720, 1}, - {"NZST", - {'N','e','w',' ','Z','e','a','l','a','n','d',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -720, 0}, - {"FJT", - {'F','i','j','i',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -720, 0}, - {"TOT", - {'T','o','n','g','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, - -780, 0} -}; - -/* TIME_GetTZAsStr: helper function that returns the given timezone as a string. - This could be done with a hash table instead of merely iterating through - a table, however with the small amount of entries (60 or so) I didn't think - it was worth it. */ -static const WCHAR* TIME_GetTZAsStr (time_t utc, int bias, int dst) -{ - char psTZName[7]; - struct tm *ptm = localtime(&utc); - int i; - - if (!strftime (psTZName, 7, "%Z", ptm)) - return (NULL); - - for (i=0; i<(sizeof(TZ_INFO) / sizeof(struct tagTZ_INFO)); i++) - { - if ( strcmp(TZ_INFO[i].psTZFromUnix, psTZName) == 0 && - TZ_INFO[i].bias == bias && - TZ_INFO[i].dst == dst - ) - return TZ_INFO[i].psTZWindows; - } - - return (NULL); -} - - -/* 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)); -} - - /*********************************************************************** * SetLocalTime (KERNEL32.@) * @@ -386,56 +142,23 @@ BOOL WINAPI GetSystemTimeAdjustment( BOOL WINAPI SetSystemTime( const SYSTEMTIME *systime) /* [in] The desired system time. */ { - struct timeval tv; - struct timezone tz; - struct tm t; - time_t sec, oldsec; - int dst, bias; - int err; + TIME_FIELDS tf; + LARGE_INTEGER t; + NTSTATUS status; - /* 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); + tf.Second = systime->wSecond; + tf.Minute = systime->wMinute; + tf.Hour = systime->wHour; + tf.Day = systime->wDay; + tf.Month = systime->wMonth; + tf.Year = systime->wYear; + tf.Milliseconds = systime->wMilliseconds; - /* 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 - 1; - t.tm_year = systime->wYear - 1900; - t.tm_isdst = dst; - sec = mktime (&t); - /* correct for timezone and daylight */ - sec += bias; + RtlTimeFieldsToTime(&tf, &t); - /* set the new time */ - tv.tv_sec = sec; - tv.tv_usec = systime->wMilliseconds * 1000; - - /* error and sanity check*/ - if( sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST ){ - err = 1; - SetLastError(ERROR_INVALID_PARAMETER); - } else { -#ifdef HAVE_SETTIMEOFDAY - err=settimeofday(&tv, NULL); /* 0 is OK, -1 is error */ - if(err == 0) - return TRUE; - SetLastError(ERROR_PRIVILEGE_NOT_HELD); -#else - err = 1; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); -#endif - } - 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; + if ((status = NtSetSystemTime(&t, NULL))) + SetLastError( RtlNtStatusToDosError(status) ); + return !status; } @@ -452,21 +175,9 @@ BOOL WINAPI SetSystemTime( DWORD WINAPI GetTimeZoneInformation( LPTIME_ZONE_INFORMATION tzinfo) /* [out] The time zone structure to be filled in. */ { - time_t gmt; - int bias, daylight; - const WCHAR *psTZ; - - - memset(tzinfo, 0, sizeof(TIME_ZONE_INFORMATION)); - - gmt = time(NULL); - bias=TIME_GetBias(gmt,&daylight); - - tzinfo->Bias = -bias / 60; - tzinfo->StandardBias = 0; - tzinfo->DaylightBias = -60; - psTZ = TIME_GetTZAsStr (gmt, (-bias/60), daylight); - if (psTZ) strcpyW( tzinfo->StandardName, psTZ ); + NTSTATUS status; + if ((status = RtlQueryTimeZoneInformation(tzinfo))) + SetLastError( RtlNtStatusToDosError(status) ); return TIME_ZONE_ID_STANDARD; } @@ -479,23 +190,14 @@ DWORD WINAPI GetTimeZoneInformation( * RETURNS * * True on successful setting of the time zone. - * - * BUGS - * - * Use the obsolete unix timezone structure and tz_dsttime member. */ BOOL WINAPI SetTimeZoneInformation( const LPTIME_ZONE_INFORMATION tzinfo) /* [in] The new time zone. */ { - struct timezone tz; - - tz.tz_minuteswest = tzinfo->Bias; -#ifdef DST_NONE - tz.tz_dsttime = DST_NONE; -#else - tz.tz_dsttime = 0; -#endif - return !settimeofday(NULL, &tz); + NTSTATUS status; + if ((status = RtlSetTimeZoneInformation(tzinfo))) + SetLastError( RtlNtStatusToDosError(status) ); + return !status; } diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 9e08473d071..1e2b87e748c 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -225,7 +225,7 @@ @ stub NtSetSystemEnvironmentValue @ stub NtSetSystemInformation @ stub NtSetSystemPowerState -@ stub NtSetSystemTime +@ stdcall NtSetSystemTime(ptr ptr) NtSetSystemTime @ stdcall NtSetTimer(long ptr ptr ptr long long ptr) NtSetTimer @ stub NtSetTimerResolution @ stdcall NtSetValueKey(long long long long long long) NtSetValueKey @@ -481,7 +481,7 @@ @ stub RtlQueryRegistryValues @ stub RtlQuerySecurityObject @ stub RtlQueryTagHeap -@ stub RtlQueryTimeZoneInformation +@ stdcall RtlQueryTimeZoneInformation(ptr) RtlQueryTimeZoneInformation @ stdcall RtlRaiseException(ptr) RtlRaiseException @ stdcall RtlRaiseStatus(long) RtlRaiseStatus @ stub RtlRandom @@ -508,7 +508,7 @@ @ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long) RtlSetOwnerSecurityDescriptor @ stdcall RtlSetSaclSecurityDescriptor(ptr long ptr long) RtlSetSaclSecurityDescriptor @ stub RtlSetSecurityObject -@ stub RtlSetTimeZoneInformation +@ stdcall RtlSetTimeZoneInformation(ptr) RtlSetTimeZoneInformation @ stub RtlSetUserFlagsHeap @ stub RtlSetUserValueHeap @ stdcall RtlSizeHeap(long long ptr) RtlSizeHeap @@ -740,7 +740,7 @@ @ stub ZwSetSystemEnvironmentValue @ stub ZwSetSystemInformation @ stub ZwSetSystemPowerState -@ stub ZwSetSystemTime +@ stdcall ZwSetSystemTime(ptr ptr) NtSetSystemTime @ stdcall ZwSetTimer(long ptr ptr ptr long long ptr) NtSetTimer @ stub ZwSetTimerResolution @ stdcall ZwSetValueKey(long long long long long long) NtSetValueKey diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c index 96ea54743d1..1da25a2d042 100644 --- a/dlls/ntdll/time.c +++ b/dlls/ntdll/time.c @@ -1,5 +1,5 @@ /* - * Conversion between Time and TimeFields + * Nt time functions. * * RtlTimeToTimeFields, RtlTimeFieldsToTime and defines are taken from ReactOS and * adapted to wine with special permissions of the author @@ -34,10 +34,222 @@ # include #endif #include "winternl.h" +#include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ntdll); +#define SETTIME_MAX_ADJUST 120 + +/* This structure is used to store strings that represent all of the time zones + * in the world. (This is used to help GetTimeZoneInformation) + */ +struct tagTZ_INFO +{ + const char *psTZFromUnix; + WCHAR psTZWindows[32]; + int bias; + int dst; +}; + +static const struct tagTZ_INFO TZ_INFO[] = +{ + {"MHT", + {'D','a','t','e','l','i','n','e',' ','S','t','a','n','d','a','r','d',' ', + 'T','i','m','e','\0'}, -720, 0}, + {"SST", + {'S','a','m','o','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, 660, 0}, + {"HST", + {'H','a','w','a','i','i','a','n',' ','S','t','a','n','d','a','r','d',' ', + 'T','i','m','e','\0'}, 600, 0}, + {"AKDT", + {'A','l','a','s','k','a','n',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, 480, 1}, + {"PDT", + {'P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, 420, 1}, + {"MST", + {'U','S',' ','M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a', + 'r','d',' ','T','i','m','e','\0'}, 420, 0}, + {"MDT", + {'M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a','r','d',' ', + 'T','i','m','e','\0'}, 360, 1}, + {"CST", + {'C','e','n','t','r','a','l',' ','A','m','e','r','i','c','a',' ','S','t', + 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, 360, 0}, + {"CDT", + {'C','e','n','t','r','a','l',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, 300, 1}, + {"COT", + {'S','A',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r', + 'd',' ','T','i','m','e','\0'}, 300, 0}, + {"EDT", + {'E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, 240, 1}, + {"EST", + {'U','S',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r', + 'd',' ','T','i','m','e','\0'}, 300, 0}, + {"ADT", + {'A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ', + 'T','i','m','e','\0'}, 180, 1}, + {"VET", + {'S','A',' ','W','e','s','t','e','r','n',' ','S','t','a','n','d','a','r', + 'd',' ','T','i','m','e','\0'}, 240, 0}, + {"CLT", + {'P','a','c','i','f','i','c',' ','S','A',' ','S','t','a','n','d','a','r', + 'd',' ','T','i','m','e','\0'}, 240, 0}, + {"NDT", + {'N','e','w','f','o','u','n','d','l','a','n','d',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, 150, 1}, + {"BRT", + {'E','.',' ','S','o','u','t','h',' ','A','m','e','r','i','c','a',' ','S', + 't','a','n','d','a','r','d',' ','T','i','m','e','\0'}, 180, 0}, + {"ART", + {'S','A',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r', + 'd',' ','T','i','m','e','\0'}, 180, 0}, + {"WGST", + {'G','r','e','e','n','l','a','n','d',' ','S','t','a','n','d','a','r','d', + ' ','T','i','m','e','\0'}, 120, 1}, + {"GST", + {'M','i','d','-','A','t','l','a','n','t','i','c',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, 120, 0}, + {"AZOST", + {'A','z','o','r','e','s',' ','S','t','a','n','d','a','r','d',' ','T','i', + 'm','e','\0'}, 0, 1}, + {"CVT", + {'C','a','p','e',' ','V','e','r','d','e',' ','S','t','a','n','d','a','r', + 'd',' ','T','i','m','e','\0'}, 60, 0}, + {"WET", + {'G','r','e','e','n','w','i','c','h',' ','S','t','a','n','d','a','r','d', + ' ','T','i','m','e','\0'}, 0, 0}, + {"BST", + {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, + -60, 1}, + {"GMT", + {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, + 0, 0}, + {"CEST", + {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','S','t','a', + 'n','d','a','r','d',' ','T','i','m','e','\0'}, -120, 1}, + {"WAT", + {'W','.',' ','C','e','n','t','r','a','l',' ','A','f','r','i','c','a',' ', + 'S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, -60, 0}, + {"EEST", + {'E','.',' ','E','u','r','o','p','e',' ','S','t','a','n','d','a','r','d', + ' ','T','i','m','e','\0'}, -180, 1}, + {"EET", + {'E','g','y','p','t',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, -120, 0}, + {"CAT", + {'S','o','u','t','h',' ','A','f','r','i','c','a',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, -120, 0}, + {"IST", + {'I','s','r','a','e','l',' ','S','t','a','n','d','a','r','d',' ','T','i', + 'm','e','\0'}, -120, 0}, + {"ADT", + {'A','r','a','b','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i', + 'm','e','\0'}, -240, 1}, + {"AST", + {'A','r','a','b',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e', + '\0'}, -180, 0}, + {"MSD", + {'R','u','s','s','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, -240, 1}, + {"EAT", + {'E','.',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d', + ' ','T','i','m','e','\0'}, -180, 0}, + {"IRST", + {'I','r','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e', + '\0'}, -270, 1}, + {"GST", + {'A','r','a','b','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, -240, 0}, + {"AZST", + {'C','a','u','c','a','s','u','s',' ','S','t','a','n','d','a','r','d',' ', + 'T','i','m','e','\0'}, -300, 1}, + {"AFT", + {'A','f','g','h','a','n','i','s','t','a','n',' ','S','t','a','n','d','a', + 'r','d',' ','T','i','m','e','\0'}, -270, 0}, + {"YEKST", + {'E','k','a','t','e','r','i','n','b','u','r','g',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, -360, 1}, + {"PKT", + {'W','e','s','t',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d', + ' ','T','i','m','e','\0'}, -300, 0}, + {"IST", + {'I','n','d','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, -330, 0}, + {"NPT", + {'N','e','p','a','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, -345, 0}, + {"ALMST", + {'N','.',' ','C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t', + 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -420, 1}, + {"BDT", + {'C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, -360, 0}, + {"LKT", + {'S','r','i',' ','L','a','n','k','a',' ','S','t','a','n','d','a','r','d', + ' ','T','i','m','e','\0'}, -360, 0}, + {"MMT", + {'M','y','a','n','m','a','r',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, -390, 0}, + {"ICT", + {'S','E',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, -420, 0}, + {"KRAST", + {'N','o','r','t','h',' ','A','s','i','a',' ','S','t','a','n','d','a','r', + 'd',' ','T','i','m','e','\0'}, -480, 1}, + {"CST", + {'C','h','i','n','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, -480, 0}, + {"IRKST", + {'N','o','r','t','h',' ','A','s','i','a',' ','E','a','s','t',' ','S','t', + 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -540, 1}, + {"SGT", + {'M','a','l','a','y',' ','P','e','n','i','n','s','u','l','a',' ','S','t', + 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -480, 0}, + {"WST", + {'W','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, -480, 0}, + {"JST", + {'T','o','k','y','o',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, -540, 0}, + {"KST", + {'K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, -540, 0}, + {"YAKST", + {'Y','a','k','u','t','s','k',' ','S','t','a','n','d','a','r','d',' ','T', + 'i','m','e','\0'}, -600, 1}, + {"CST", + {'C','e','n','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a', + 'n','d','a','r','d',' ','T','i','m','e','\0'}, -570, 0}, + {"EST", + {'E','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, -600, 0}, + {"GST", + {'W','e','s','t',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d', + 'a','r','d',' ','T','i','m','e','\0'}, -600, 0}, + {"VLAST", + {'V','l','a','d','i','v','o','s','t','o','k',' ','S','t','a','n','d','a', + 'r','d',' ','T','i','m','e','\0'}, -660, 1}, + {"MAGST", + {'C','e','n','t','r','a','l',' ','P','a','c','i','f','i','c',' ','S','t', + 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -720, 1}, + {"NZST", + {'N','e','w',' ','Z','e','a','l','a','n','d',' ','S','t','a','n','d','a', + 'r','d',' ','T','i','m','e','\0'}, -720, 0}, + {"FJT", + {'F','i','j','i',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e', + '\0'}, -720, 0}, + {"TOT", + {'T','o','n','g','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m', + 'e','\0'}, -780, 0} +}; + +/*********** start of code by Rex Jolliff (rex@lvcablemodem.com) **************/ + #define TICKSPERSEC 10000000 #define TICKSPERMSEC 10000 #define SECSPERDAY 86400 @@ -77,12 +289,19 @@ static inline void NormalizeTimeFields(CSHORT *FieldToNormalize, CSHORT *CarryFi } /****************************************************************************** - * RtlTimeToTimeFields [NTDLL.@] + * RtlTimeToTimeFields [NTDLL.@] * + * Parses Time into a TimeFields structure. + * + * PARAMS: + * liTime [I]: Time to convert to timefields. + * TimeFields [O]: Pointer to TIME_FIELDS structure to hold parsed info. + * + * RETURNS: + * Nothing. */ - VOID WINAPI RtlTimeToTimeFields( - PLARGE_INTEGER liTime, + const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) { const int *Months; @@ -137,8 +356,17 @@ VOID WINAPI RtlTimeToTimeFields( } /****************************************************************************** - * RtlTimeFieldsToTime [NTDLL.@] + * RtlTimeFieldsToTime [NTDLL.@] * + * Converts a TIME_FIELDS structure to time. + * + * PARAMS: + * ftTimeFields [I]: Time fields structure to convert. + * Time [O]: Converted time. + * + * RETURNS: + * TRUE: Successfull + * FALSE: Failure. */ BOOLEAN WINAPI RtlTimeFieldsToTime( PTIME_FIELDS tfTimeFields, @@ -183,10 +411,20 @@ BOOLEAN WINAPI RtlTimeFieldsToTime( return TRUE; } -/************* end of code by Rex Jolliff (rex@lvcablemodem.com) *******************/ +/************ end of code by Rex Jolliff (rex@lvcablemodem.com) ***************/ + /****************************************************************************** - * RtlSystemTimeToLocalTime [NTDLL.@] + * RtlSystemTimeToLocalTime [NTDLL.@] + * + * Converts system Time to local time. + * + * PARAMS: + * SystemTime [I]: System time to convert. + * LocalTime [O]: Local time of the supplied system time. + * + * RETURNS: + * Nothing. */ VOID WINAPI RtlSystemTimeToLocalTime( IN PLARGE_INTEGER SystemTime, @@ -198,7 +436,17 @@ VOID WINAPI RtlSystemTimeToLocalTime( } /****************************************************************************** - * RtlTimeToSecondsSince1970 [NTDLL.@] + * RtlTimeToSecondsSince1970 [NTDLL.@] + * + * Converts Time to seconds since 1970. + * + * PARAMS: + * time [I]: Time to convert. + * res [O]: Pointer to a LONG to recieve the seconds since 1970. + * + * RETURNS: + * TRUE: Successfull. + * FALSE: Failure. */ BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *time, PULONG res ) { @@ -211,7 +459,17 @@ BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *time, PULONG res } /****************************************************************************** - * RtlTimeToSecondsSince1980 [NTDLL.@] + * RtlTimeToSecondsSince1980 [NTDLL.@] + * + * Converts Time to seconds since 1980. + * + * PARAMS: + * time [I]: Time to convert. + * res [O]: Pointer to a integer to recieve the time since 1980. + * + * RETURNS: + * TRUE: Successfull + * FALSE: Failure. */ BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *time, LPDWORD res ) { @@ -224,7 +482,16 @@ BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *time, LPDWORD res } /****************************************************************************** - * RtlSecondsSince1970ToTime [NTDLL.@] + * RtlSecondsSince1970ToTime [NTDLL.@] + * + * Converts seconds since 1970 to time. + * + * PARAMS: + * time [I]: Seconds since 1970 to convert. + * res [O]: Seconds since 1970 in Time. + * + * RETURNS: + * Nothing. */ void WINAPI RtlSecondsSince1970ToTime( DWORD time, LARGE_INTEGER *res ) { @@ -234,7 +501,16 @@ void WINAPI RtlSecondsSince1970ToTime( DWORD time, LARGE_INTEGER *res ) } /****************************************************************************** - * RtlSecondsSince1980ToTime [NTDLL.@] + * RtlSecondsSince1980ToTime [NTDLL.@] + * + * Converts seconds since 1980 to time. + * + * PARAMS: + * time [I]: Seconds since 1980 to convert. + * res [O]: Seconds since 1980 in Time. + * + * RETURNS: + * Nothing. */ void WINAPI RtlSecondsSince1980ToTime( DWORD time, LARGE_INTEGER *res ) { @@ -244,8 +520,19 @@ void WINAPI RtlSecondsSince1980ToTime( DWORD time, LARGE_INTEGER *res ) } /****************************************************************************** - * RtlTimeToElapsedTimeFields [NTDLL.@] - * FIXME: prototype guessed + * RtlTimeToElapsedTimeFields [NTDLL.@] + * + * ?? + * + * PARAMS: + * liTime [?]: ?? + * TimeFields [?]: ?? + * + * RETURNS: + * Nothing. + * + * FIXME: + * Prototype guessed. */ VOID WINAPI RtlTimeToElapsedTimeFields( PLARGE_INTEGER liTime, @@ -255,8 +542,16 @@ VOID WINAPI RtlTimeToElapsedTimeFields( } /*********************************************************************** - * NtQuerySystemTime (NTDLL.@) - * ZwQuerySystemTime (NTDLL.@) + * NtQuerySystemTime [NTDLL.@] + * ZwQuerySystemTime [NTDLL.@] + * + * Gets the current system time. + * + * PARAMS: + * time [O]: The current system time. + * + * RETURNS: + * Status. */ NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER time ) { @@ -269,3 +564,199 @@ NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER time ) time->s.HighPart = (DWORD)(secs >> 32); return STATUS_SUCCESS; } + +/*********************************************************************** + * TIME_GetBias [internal] + * + * Helper function calculates delta local time from UTC. + * + * PARAMS: + * utc [I]: The current utc time. + * pdaylight [I]: Local daylight. + * + * RETURNS: + * The bias for the current timezone. + */ +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)); +} + +/*********************************************************************** + * TIME_GetTZAsStr [internal] + * + * Helper function that returns the given timezone as a string. + * + * PARAMS: + * utc [I]: The current utc time. + * bias [I]: The bias of the current timezone. + * dst [I]: ?? + * + * RETURNS: + * Timezone name. + * + * NOTES: + * This could be done with a hash table instead of merely iterating through a + * table, however with the small amount of entries (60 or so) I didn't think + * it was worth it. + */ +static const WCHAR* TIME_GetTZAsStr (time_t utc, int bias, int dst) +{ + char psTZName[7]; + struct tm *ptm = localtime(&utc); + int i; + + if (!strftime (psTZName, 7, "%Z", ptm)) + return (NULL); + + for (i=0; i<(sizeof(TZ_INFO) / sizeof(struct tagTZ_INFO)); i++) + { + if ( strcmp(TZ_INFO[i].psTZFromUnix, psTZName) == 0 && + TZ_INFO[i].bias == bias && + TZ_INFO[i].dst == dst + ) + return TZ_INFO[i].psTZWindows; + } + + return (NULL); +} + +/*********************************************************************** + * RtlQueryTimeZoneInformation [NTDLL.@] + * + * Returns the timezone. + * + * PARAMS: + * tzinfo [O]: Retrieves the timezone info. + * + * RETURNS: + * Status. + */ +NTSTATUS WINAPI RtlQueryTimeZoneInformation(LPTIME_ZONE_INFORMATION tzinfo) +{ + time_t gmt; + int bias, daylight; + const WCHAR *psTZ; + + memset(tzinfo, 0, sizeof(TIME_ZONE_INFORMATION)); + + gmt = time(NULL); + bias = TIME_GetBias(gmt, &daylight); + + tzinfo->Bias = -bias / 60; + tzinfo->StandardBias = 0; + tzinfo->DaylightBias = -60; + psTZ = TIME_GetTZAsStr (gmt, (-bias/60), daylight); + if (psTZ) strcpyW( tzinfo->StandardName, psTZ ); + return STATUS_SUCCESS; +} + +/*********************************************************************** + * RtlSetTimeZoneInformation [NTDLL.@] + * + * Sets the current time zone. + * + * PARAMS: + * tzinfo [I]: Timezone information used to set timezone. + * + * RETURNS: + * Status. + * + * BUGS: + * Uses the obsolete unix timezone structure and tz_dsttime member. + */ +NTSTATUS WINAPI RtlSetTimeZoneInformation( const TIME_ZONE_INFORMATION *tzinfo ) +{ + struct timezone tz; + + tz.tz_minuteswest = tzinfo->Bias; +#ifdef DST_NONE + tz.tz_dsttime = DST_NONE; +#else + tz.tz_dsttime = 0; +#endif + if(!settimeofday(NULL, &tz)) + return STATUS_SUCCESS; + return STATUS_PRIVILEGE_NOT_HELD; +} + +/*********************************************************************** + * NtSetSystemTime [NTDLL.@] + * ZwSetSystemTime [NTDLL.@] + * + * Sets the system time. + * + * PARAM: + * NewTime [I]: The time to set the system time to. + * OldTime [O]: Optional (ie. can be NULL). Old Time. + * + * RETURNS: + * Status. + */ +NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *NewTime, LARGE_INTEGER *OldTime) +{ + TIME_FIELDS tf; + struct timeval tv; + struct timezone tz; + struct tm t; + time_t sec, oldsec; + int dst, bias; + int err; + + /* Return the old time if necessary */ + if(OldTime) + NtQuerySystemTime(OldTime); + + RtlTimeToTimeFields(NewTime, &tf); + + /* 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 = tf.Second; + t.tm_min = tf.Minute; + t.tm_hour = tf.Hour; + t.tm_mday = tf.Day; + t.tm_mon = tf.Month - 1; + t.tm_year = tf.Year - 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 = tf.Milliseconds * 1000; + + /* error and sanity check*/ + if(sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST) { + err = 2; + } else { +#ifdef HAVE_SETTIMEOFDAY + err = settimeofday(&tv, NULL); /* 0 is OK, -1 is error */ + if(err == 0) + return STATUS_SUCCESS; +#else + err = 1; +#endif + } + + ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n", + tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second, + sec-oldsec, err == -1 ? "No Permission" : + sec == (time_t)-1 ? "" : "is too large." ); + + if(err == 2) + return STATUS_INVALID_PARAMETER; + else if(err == -1) + return STATUS_PRIVILEGE_NOT_HELD; + else + return STATUS_NOT_IMPLEMENTED; +} diff --git a/include/winternl.h b/include/winternl.h index d9a096f88d4..f0db2bbbe5e 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -864,6 +864,7 @@ NTSTATUS WINAPI NtSaveKey(HKEY,HANDLE); NTSTATUS WINAPI NtSetEvent(HANDLE,PULONG); NTSTATUS WINAPI NtSetInformationKey(HKEY,const int,PVOID,ULONG); NTSTATUS WINAPI NtSetSecurityObject(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR); +NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER*,LARGE_INTEGER*); NTSTATUS WINAPI NtSetValueKey(HKEY,const UNICODE_STRING *,ULONG,ULONG,const void *,ULONG); NTSTATUS WINAPI NtTerminateProcess(HANDLE,LONG); NTSTATUS WINAPI NtTerminateThread(HANDLE,LONG); @@ -1013,7 +1014,7 @@ BOOLEAN WINAPI RtlPrefixString(const STRING*,const STRING*,BOOLEAN); BOOLEAN WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN); DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD,PUNICODE_STRING,PUNICODE_STRING) ; - +NTSTATUS WINAPI RtlQueryTimeZoneInformation(LPTIME_ZONE_INFORMATION); void WINAPI RtlRaiseException(PEXCEPTION_RECORD); void WINAPI RtlRaiseStatus(NTSTATUS); PVOID WINAPI RtlReAllocateHeap(HANDLE,ULONG,PVOID,ULONG); @@ -1029,12 +1030,13 @@ DWORD WINAPI RtlSetEnvironmentVariable(DWORD,PUNICODE_STRING,PUNICODE_STRING NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID,BOOLEAN); NTSTATUS WINAPI RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID,BOOLEAN); NTSTATUS WINAPI RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR,BOOLEAN,PACL,BOOLEAN); +NTSTATUS WINAPI RtlSetTimeZoneInformation(const TIME_ZONE_INFORMATION*); ULONG WINAPI RtlSizeHeap(HANDLE,ULONG,PVOID); LPDWORD WINAPI RtlSubAuthoritySid(PSID,DWORD); LPBYTE WINAPI RtlSubAuthorityCountSid(PSID); void WINAPI RtlSystemTimeToLocalTime(PLARGE_INTEGER,PLARGE_INTEGER); -void WINAPI RtlTimeToTimeFields(PLARGE_INTEGER,PTIME_FIELDS); +void WINAPI RtlTimeToTimeFields(const LARGE_INTEGER*,PTIME_FIELDS); BOOLEAN WINAPI RtlTimeFieldsToTime(PTIME_FIELDS,PLARGE_INTEGER); void WINAPI RtlTimeToElapsedTimeFields(PLARGE_INTEGER,PTIME_FIELDS); BOOLEAN WINAPI RtlTimeToSecondsSince1970(const LARGE_INTEGER *,PULONG);