Vincent Povirk : kernel32: Implement GetTimeZoneInformationForYear.
Alexandre Julliard
julliard at winehq.org
Tue Feb 28 03:45:56 CST 2017
Module: wine
Branch: oldstable
Commit: fe89a8a45412530e387d81b5e969f3538575dd5a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fe89a8a45412530e387d81b5e969f3538575dd5a
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Fri Jan 29 14:31:27 2016 -0600
kernel32: Implement GetTimeZoneInformationForYear.
Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit b922b55182ca2b51bf2599369c471b3920bfb635)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>
---
.../api-ms-win-core-sysinfo-l1-1-0.spec | 2 +-
.../api-ms-win-core-timezone-l1-1-0.spec | 2 +-
dlls/kernel32/kernel32.spec | 2 +-
dlls/kernel32/tests/time.c | 2 +-
dlls/kernel32/time.c | 197 +++++++++++++++++++++
5 files changed, 201 insertions(+), 4 deletions(-)
diff --git a/dlls/api-ms-win-core-sysinfo-l1-1-0/api-ms-win-core-sysinfo-l1-1-0.spec b/dlls/api-ms-win-core-sysinfo-l1-1-0/api-ms-win-core-sysinfo-l1-1-0.spec
index 5044394..cafde5e 100644
--- a/dlls/api-ms-win-core-sysinfo-l1-1-0/api-ms-win-core-sysinfo-l1-1-0.spec
+++ b/dlls/api-ms-win-core-sysinfo-l1-1-0/api-ms-win-core-sysinfo-l1-1-0.spec
@@ -15,7 +15,7 @@
@ stdcall -ret64 GetTickCount64() kernel32.GetTickCount64
@ stdcall GetTickCount() kernel32.GetTickCount
@ stdcall GetTimeZoneInformation(ptr) kernel32.GetTimeZoneInformation
-@ stub GetTimeZoneInformationForYear
+@ stdcall GetTimeZoneInformationForYear(long ptr ptr) kernel32.GetTimeZoneInformationForYear
@ stdcall GetVersion() kernel32.GetVersion
@ stdcall GetVersionExA(ptr) kernel32.GetVersionExA
@ stdcall GetVersionExW(ptr) kernel32.GetVersionExW
diff --git a/dlls/api-ms-win-core-timezone-l1-1-0/api-ms-win-core-timezone-l1-1-0.spec b/dlls/api-ms-win-core-timezone-l1-1-0/api-ms-win-core-timezone-l1-1-0.spec
index f93cc10..b452879 100644
--- a/dlls/api-ms-win-core-timezone-l1-1-0/api-ms-win-core-timezone-l1-1-0.spec
+++ b/dlls/api-ms-win-core-timezone-l1-1-0/api-ms-win-core-timezone-l1-1-0.spec
@@ -3,7 +3,7 @@
@ stdcall GetDynamicTimeZoneInformation(ptr) kernel32.GetDynamicTimeZoneInformation
@ stub GetDynamicTimeZoneInformationEffectiveYears
@ stdcall GetTimeZoneInformation(ptr) kernel32.GetTimeZoneInformation
-@ stub GetTimeZoneInformationForYear
+@ stdcall GetTimeZoneInformationForYear(long ptr ptr) kernel32.GetTimeZoneInformationForYear
@ stub SetDynamicTimeZoneInformation
@ stdcall SetTimeZoneInformation(ptr) kernel32.SetTimeZoneInformation
@ stdcall SystemTimeToFileTime(ptr ptr) kernel32.SystemTimeToFileTime
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 02475c5..ec2c109 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -860,7 +860,7 @@
@ stdcall GetTimeFormatEx(wstr long ptr wstr ptr long)
@ stdcall GetTimeFormatW(long long ptr wstr ptr long)
@ stdcall GetTimeZoneInformation(ptr)
-# @ stub GetTimeZoneInformationForYear
+@ stdcall GetTimeZoneInformationForYear(long ptr ptr)
@ stdcall GetThreadUILanguage()
# @ stub GetUILanguageInfo
# @ stub -arch=x86_64 GetUmsCompletionListEvent
diff --git a/dlls/kernel32/tests/time.c b/dlls/kernel32/tests/time.c
index cd100f2..53af39c 100644
--- a/dlls/kernel32/tests/time.c
+++ b/dlls/kernel32/tests/time.c
@@ -921,7 +921,7 @@ static void test_GetTimeZoneInformationForYear(void)
if (!pGetTimeZoneInformationForYear || !pGetDynamicTimeZoneInformation)
{
- todo_wine win_skip("GetTimeZoneInformationForYear not available\n");
+ win_skip("GetTimeZoneInformationForYear not available\n");
return;
}
diff --git a/dlls/kernel32/time.c b/dlls/kernel32/time.c
index ac39fde..b7a7918 100644
--- a/dlls/kernel32/time.c
+++ b/dlls/kernel32/time.c
@@ -282,6 +282,179 @@ static BOOL TIME_GetTimezoneBias( const TIME_ZONE_INFORMATION *pTZinfo,
return TRUE;
}
+/***********************************************************************
+ * TIME_GetSpecificTimeZoneKey
+ *
+ * Opens the registry key for the time zone with the given name.
+ *
+ * PARAMS
+ * key_name [in] The time zone name.
+ * result [out] The open registry key handle.
+ *
+ * RETURNS
+ * TRUE if successful.
+ */
+static BOOL TIME_GetSpecificTimeZoneKey( const WCHAR *key_name, HANDLE *result )
+{
+ static const WCHAR Time_ZonesW[] = { '\\','R','E','G','I','S','T','R','Y','\\',
+ 'M','a','c','h','i','n','e','\\',
+ 'S','o','f','t','w','a','r','e','\\',
+ 'M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s',' ','N','T','\\',
+ 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'T','i','m','e',' ','Z','o','n','e','s',0 };
+ HANDLE time_zones_key;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+ NTSTATUS status;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &nameW, Time_ZonesW );
+ status = NtOpenKey( &time_zones_key, KEY_READ, &attr );
+ if (status)
+ {
+ WARN("Unable to open the time zones key\n");
+ SetLastError( RtlNtStatusToDosError(status) );
+ return FALSE;
+ }
+
+ attr.RootDirectory = time_zones_key;
+ RtlInitUnicodeString( &nameW, key_name );
+ status = NtOpenKey( result, KEY_READ, &attr );
+
+ NtClose( time_zones_key );
+
+ if (status)
+ {
+ SetLastError( RtlNtStatusToDosError(status) );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL reg_query_value(HKEY hkey, LPCWSTR name, DWORD type, void *data, DWORD count)
+{
+ UNICODE_STRING nameW;
+ char buf[256];
+ KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buf;
+ NTSTATUS status;
+
+ if (count > sizeof(buf) - sizeof(KEY_VALUE_PARTIAL_INFORMATION))
+ return FALSE;
+
+ RtlInitUnicodeString(&nameW, name);
+
+ if ((status = NtQueryValueKey(hkey, &nameW, KeyValuePartialInformation,
+ buf, sizeof(buf), &count)))
+ {
+ SetLastError( RtlNtStatusToDosError(status) );
+ return FALSE;
+ }
+
+ if (info->Type != type)
+ {
+ SetLastError( ERROR_DATATYPE_MISMATCH );
+ return FALSE;
+ }
+
+ memcpy(data, info->Data, info->DataLength);
+ return TRUE;
+}
+
+/***********************************************************************
+ * TIME_GetSpecificTimeZoneInfo
+ *
+ * Returns time zone information for the given time zone and year.
+ *
+ * PARAMS
+ * key_name [in] The time zone name.
+ * year [in] The year, if Dynamic DST is used.
+ * dynamic [in] Whether to use Dynamic DST.
+ * result [out] The time zone information.
+ *
+ * RETURNS
+ * TRUE if successful.
+ */
+static BOOL TIME_GetSpecificTimeZoneInfo( const WCHAR *key_name, WORD year,
+ BOOL dynamic, DYNAMIC_TIME_ZONE_INFORMATION *tzinfo )
+{
+ static const WCHAR Dynamic_DstW[] = { 'D','y','n','a','m','i','c',' ','D','S','T',0 };
+ static const WCHAR fmtW[] = { '%','d',0 };
+ static const WCHAR stdW[] = { 'S','t','d',0 };
+ static const WCHAR dltW[] = { 'D','l','t',0 };
+ static const WCHAR tziW[] = { 'T','Z','I',0 };
+ HANDLE time_zone_key, dynamic_dst_key;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+ WCHAR yearW[16];
+ BOOL got_reg_data = FALSE;
+ struct tz_reg_data
+ {
+ LONG bias;
+ LONG std_bias;
+ LONG dlt_bias;
+ SYSTEMTIME std_date;
+ SYSTEMTIME dlt_date;
+ } tz_data;
+
+ if (!TIME_GetSpecificTimeZoneKey( key_name, &time_zone_key ))
+ return FALSE;
+
+ if (!reg_query_value( time_zone_key, stdW, REG_SZ, tzinfo->StandardName, sizeof(tzinfo->StandardName)) ||
+ !reg_query_value( time_zone_key, dltW, REG_SZ, tzinfo->DaylightName, sizeof(tzinfo->DaylightName)))
+ {
+ NtClose( time_zone_key );
+ return FALSE;
+ }
+
+ lstrcpyW(tzinfo->TimeZoneKeyName, key_name);
+
+ if (dynamic)
+ {
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = time_zone_key;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &nameW, Dynamic_DstW );
+ if (!NtOpenKey( &dynamic_dst_key, KEY_READ, &attr ))
+ {
+ sprintfW( yearW, fmtW, year );
+ got_reg_data = reg_query_value( dynamic_dst_key, yearW, REG_BINARY, &tz_data, sizeof(tz_data) );
+
+ NtClose( dynamic_dst_key );
+ }
+ }
+
+ if (!got_reg_data)
+ {
+ if (!reg_query_value( time_zone_key, tziW, REG_BINARY, &tz_data, sizeof(tz_data) ))
+ {
+ NtClose( time_zone_key );
+ return FALSE;
+ }
+ }
+
+ tzinfo->Bias = tz_data.bias;
+ tzinfo->StandardBias = tz_data.std_bias;
+ tzinfo->DaylightBias = tz_data.dlt_bias;
+ tzinfo->StandardDate = tz_data.std_date;
+ tzinfo->DaylightDate = tz_data.dlt_date;
+
+ tzinfo->DynamicDaylightTimeDisabled = !dynamic;
+
+ NtClose( time_zone_key );
+
+ return TRUE;
+}
+
/***********************************************************************
* SetLocalTime (KERNEL32.@)
@@ -418,6 +591,30 @@ DWORD WINAPI GetTimeZoneInformation( LPTIME_ZONE_INFORMATION tzinfo )
}
/***********************************************************************
+ * GetTimeZoneInformationForYear (KERNEL32.@)
+ */
+BOOL WINAPI GetTimeZoneInformationForYear( USHORT wYear,
+ PDYNAMIC_TIME_ZONE_INFORMATION pdtzi, LPTIME_ZONE_INFORMATION ptzi )
+{
+ DYNAMIC_TIME_ZONE_INFORMATION local_dtzi, result;
+
+ if (!pdtzi)
+ {
+ if (GetDynamicTimeZoneInformation(&local_dtzi) == TIME_ZONE_ID_INVALID)
+ return FALSE;
+ pdtzi = &local_dtzi;
+ }
+
+ if (!TIME_GetSpecificTimeZoneInfo(pdtzi->TimeZoneKeyName, wYear,
+ !pdtzi->DynamicDaylightTimeDisabled, &result))
+ return FALSE;
+
+ memcpy(ptzi, &result, sizeof(*ptzi));
+
+ return TRUE;
+}
+
+/***********************************************************************
* SetTimeZoneInformation (KERNEL32.@)
*
* Change the settings of the current local time zone.
More information about the wine-cvs
mailing list