<data name="Argument_InvalidPathChars" xml:space="preserve">
<value>Illegal characters in path.</value>
</data>
- <data name="Argument_InvalidREG_TZI_FORMAT" xml:space="preserve">
- <value>The REG_TZI_FORMAT structure is corrupt.</value>
- </data>
<data name="Argument_InvalidRegistryViewCheck" xml:space="preserve">
<value>The specified RegistryView value is invalid.</value>
</data>
<data name="IO_InvalidReadLength" xml:space="preserve">
<value>The read operation returned an invalid length.</value>
</data>
-</root>
\ No newline at end of file
+</root>
<Compile Include="$(BclSourcesRoot)\System\Globalization\GlobalizationMode.Windows.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ClrThreadPoolBoundHandle.Windows.cs" />
<Compile Include="$(BclSourcesRoot)\System\Environment.Windows.cs" />
- <Compile Include="$(BclSourcesRoot)\System\TimeZoneInfo.Win32.cs" />
</ItemGroup>
<!-- Include additional sources shared files in the compilation -->
<ItemGroup>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ internal const uint MUI_PREFERRED_UI_LANGUAGES = 0x10;
+
+ [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
+ internal static extern bool GetFileMUIPath(uint flags, String filePath, [Out] StringBuilder language, ref int languageLength, [Out] StringBuilder fileMuiPath, ref int fileMuiPathLength, ref Int64 enumerator);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct REG_TZI_FORMAT
+ {
+ internal int Bias;
+ internal int StandardBias;
+ internal int DaylightBias;
+ internal SYSTEMTIME StandardDate;
+ internal SYSTEMTIME DaylightDate;
+
+ internal REG_TZI_FORMAT(in TIME_ZONE_INFORMATION tzi)
+ {
+ Bias = tzi.Bias;
+ StandardDate = tzi.StandardDate;
+ StandardBias = tzi.StandardBias;
+ DaylightDate = tzi.DaylightDate;
+ DaylightBias = tzi.DaylightBias;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ internal struct SYSTEMTIME
+ {
+ internal ushort Year;
+ internal ushort Month;
+ internal ushort DayOfWeek;
+ internal ushort Day;
+ internal ushort Hour;
+ internal ushort Minute;
+ internal ushort Second;
+ internal ushort Milliseconds;
+
+ internal bool Equals(in SYSTEMTIME other) =>
+ Year == other.Year &&
+ Month == other.Month &&
+ DayOfWeek == other.DayOfWeek &&
+ Day == other.Day &&
+ Hour == other.Hour &&
+ Minute == other.Minute &&
+ Second == other.Second &&
+ Milliseconds == other.Milliseconds;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal unsafe struct TIME_DYNAMIC_ZONE_INFORMATION
+ {
+ internal int Bias;
+ internal fixed char StandardName[32];
+ internal SYSTEMTIME StandardDate;
+ internal int StandardBias;
+ internal fixed char DaylightName[32];
+ internal SYSTEMTIME DaylightDate;
+ internal int DaylightBias;
+ internal fixed char TimeZoneKeyName[128];
+ internal byte DynamicDaylightTimeDisabled;
+
+ internal string GetTimeZoneKeyName()
+ {
+ fixed (char* p = TimeZoneKeyName)
+ return new string(p);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal unsafe struct TIME_ZONE_INFORMATION
+ {
+ internal int Bias;
+ internal fixed char StandardName[32];
+ internal SYSTEMTIME StandardDate;
+ internal int StandardBias;
+ internal fixed char DaylightName[32];
+ internal SYSTEMTIME DaylightDate;
+ internal int DaylightBias;
+
+ internal TIME_ZONE_INFORMATION(in TIME_DYNAMIC_ZONE_INFORMATION dtzi)
+ {
+ // The start of TIME_DYNAMIC_ZONE_INFORMATION has identical layout as TIME_ZONE_INFORMATION
+ fixed (TIME_ZONE_INFORMATION* pTo = &this)
+ fixed (TIME_DYNAMIC_ZONE_INFORMATION* pFrom = &dtzi)
+ *pTo = *(TIME_ZONE_INFORMATION*)pFrom;
+ }
+
+ internal string GetStandardName()
+ {
+ fixed (char* p = StandardName)
+ return new string(p);
+ }
+
+ internal string GetDaylightName()
+ {
+ fixed (char* p = DaylightName)
+ return new string(p);
+ }
+ }
+
+ internal const uint TIME_ZONE_ID_INVALID = unchecked((uint)-1);
+
+ [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
+ internal extern static uint GetDynamicTimeZoneInformation(out TIME_DYNAMIC_ZONE_INFORMATION pTimeZoneInformation);
+
+ [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
+ internal static extern uint GetTimeZoneInformation(out TIME_ZONE_INFORMATION lpTimeZoneInformation);
+ }
+}
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_NativeOverlapped.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Idna.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Normalization.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysAllocStringLen.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysFreeString.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysStringLen.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsWindows) and '$(EnableWinRT)' != 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Win32.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Win32.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.LoadLibraryEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FreeLibrary.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CreateFile.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.MUI.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.Registry.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.Constants.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.SendMessageTimeout.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.LoadString.cs" />
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
-using REG_TZI_FORMAT = Microsoft.Win32.Win32Native.RegistryTimeZoneInformation;
-using TIME_ZONE_INFORMATION = Microsoft.Win32.Win32Native.TimeZoneInformation;
-using TIME_DYNAMIC_ZONE_INFORMATION = Microsoft.Win32.Win32Native.DynamicTimeZoneInformation;
+
+using Internal.Runtime.CompilerServices;
+
+using REG_TZI_FORMAT = Interop.Kernel32.REG_TZI_FORMAT;
+using TIME_ZONE_INFORMATION = Interop.Kernel32.TIME_ZONE_INFORMATION;
+using TIME_DYNAMIC_ZONE_INFORMATION = Interop.Kernel32.TIME_DYNAMIC_ZONE_INFORMATION;
namespace System
{
private const string LastEntryValue = "LastEntry";
private const int MaxKeyLength = 255;
- private const int RegByteLength = 44;
#pragma warning disable 0420
private sealed partial class CachedData
{
// load the data from the OS
TIME_ZONE_INFORMATION timeZoneInformation;
- long result = UnsafeNativeMethods.GetTimeZoneInformation(out timeZoneInformation);
- return result == Win32Native.TIME_ZONE_ID_INVALID ?
+ uint result = Interop.Kernel32.GetTimeZoneInformation(out timeZoneInformation);
+ return result == Interop.Kernel32.TIME_ZONE_ID_INVALID ?
CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId) :
GetLocalTimeZoneFromWin32Data(timeZoneInformation, dstDisabled: false);
}
private TimeZoneInfo(in TIME_ZONE_INFORMATION zone, bool dstDisabled)
{
- if (string.IsNullOrEmpty(zone.StandardName))
+ string standardName = zone.GetStandardName();
+ if (standardName.Length == 0)
{
_id = LocalId; // the ID must contain at least 1 character - initialize _id to "Local"
}
else
{
- _id = zone.StandardName;
+ _id = standardName;
}
_baseUtcOffset = new TimeSpan(0, -(zone.Bias), 0);
AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(regZone, DateTime.MinValue.Date, DateTime.MaxValue.Date, zone.Bias);
if (rule != null)
{
- _adjustmentRules = new AdjustmentRule[1];
- _adjustmentRules[0] = rule;
+ _adjustmentRules = new[] { rule };
}
}
ValidateTimeZoneInfo(_id, _baseUtcOffset, _adjustmentRules, out _supportsDaylightSavingTime);
- _displayName = zone.StandardName;
- _standardDisplayName = zone.StandardName;
- _daylightDisplayName = zone.DaylightName;
+ _displayName = standardName;
+ _standardDisplayName = standardName;
+ _daylightDisplayName = zone.GetDaylightName();
}
/// <summary>
/// This check is only meant to be used for "Local".
/// </summary>
private static bool CheckDaylightSavingTimeNotSupported(in TIME_ZONE_INFORMATION timeZone) =>
- timeZone.DaylightDate.Year == timeZone.StandardDate.Year &&
- timeZone.DaylightDate.Month == timeZone.StandardDate.Month &&
- timeZone.DaylightDate.DayOfWeek == timeZone.StandardDate.DayOfWeek &&
- timeZone.DaylightDate.Day == timeZone.StandardDate.Day &&
- timeZone.DaylightDate.Hour == timeZone.StandardDate.Hour &&
- timeZone.DaylightDate.Minute == timeZone.StandardDate.Minute &&
- timeZone.DaylightDate.Second == timeZone.StandardDate.Second &&
- timeZone.DaylightDate.Milliseconds == timeZone.StandardDate.Milliseconds;
+ timeZone.DaylightDate.Equals(timeZone.StandardDate);
/// <summary>
/// Converts a REG_TZI_FORMAT struct to an AdjustmentRule.
var dynamicTimeZoneInformation = new TIME_DYNAMIC_ZONE_INFORMATION();
// call kernel32!GetDynamicTimeZoneInformation...
- int result = UnsafeNativeMethods.GetDynamicTimeZoneInformation(out dynamicTimeZoneInformation);
- if (result == Win32Native.TIME_ZONE_ID_INVALID)
+ uint result = Interop.Kernel32.GetDynamicTimeZoneInformation(out dynamicTimeZoneInformation);
+ if (result == Interop.Kernel32.TIME_ZONE_ID_INVALID)
{
// return a dummy entry
return CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId);
}
- var timeZoneInformation = new TIME_ZONE_INFORMATION(dynamicTimeZoneInformation);
-
- bool dstDisabled = dynamicTimeZoneInformation.DynamicDaylightTimeDisabled;
-
// check to see if we can use the key name returned from the API call
- if (!string.IsNullOrEmpty(dynamicTimeZoneInformation.TimeZoneKeyName))
+ string dynamicTimeZoneKeyName = dynamicTimeZoneInformation.GetTimeZoneKeyName();
+ if (dynamicTimeZoneKeyName.Length != 0)
{
TimeZoneInfo zone;
Exception ex;
- if (TryGetTimeZone(dynamicTimeZoneInformation.TimeZoneKeyName, dstDisabled, out zone, out ex, cachedData) == TimeZoneInfoResult.Success)
+ if (TryGetTimeZone(dynamicTimeZoneKeyName, dynamicTimeZoneInformation.DynamicDaylightTimeDisabled != 0, out zone, out ex, cachedData) == TimeZoneInfoResult.Success)
{
// successfully loaded the time zone from the registry
return zone;
}
}
+ var timeZoneInformation = new TIME_ZONE_INFORMATION(dynamicTimeZoneInformation);
+
// the key name was not returned or it pointed to a bogus entry - search for the entry ourselves
- string id = FindIdFromTimeZoneInformation(timeZoneInformation, out dstDisabled);
+ string id = FindIdFromTimeZoneInformation(timeZoneInformation, out bool dstDisabled);
if (id != null)
{
{
throw new ArgumentNullException(nameof(id));
}
- else if (id.Length == 0 || id.Length > MaxKeyLength || id.Contains('\0'))
+ if (id.Length == 0 || id.Length > MaxKeyLength || id.Contains('\0'))
{
throw new TimeZoneNotFoundException(SR.Format(SR.TimeZoneNotFound_MissingData, id));
}
/// </summary>
private static bool TryCreateAdjustmentRules(string id, in REG_TZI_FORMAT defaultTimeZoneInformation, out AdjustmentRule[] rules, out Exception e, int defaultBaseUtcOffset)
{
+ rules = null;
e = null;
try
{
AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(
defaultTimeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);
- rules = rule == null ? null : new[] { rule };
+ if (rule != null)
+ {
+ rules = new[] { rule };
+ }
return true;
}
if (first == -1 || last == -1 || first > last)
{
- rules = null;
return false;
}
// read the first year entry
REG_TZI_FORMAT dtzi;
- byte[] regValue = dynamicKey.GetValue(first.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as byte[];
- if (regValue == null || regValue.Length != RegByteLength)
+
+ if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, first.ToString(CultureInfo.InvariantCulture), out dtzi))
{
- rules = null;
return false;
}
- dtzi = new REG_TZI_FORMAT(regValue);
if (first == last)
{
// there is just 1 dynamic rule for this time zone.
AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);
- rules = rule == null ? null : new[] { rule };
+ if (rule != null)
+ {
+ rules = new[] { rule };
+ }
return true;
}
// read the middle year entries
for (int i = first + 1; i < last; i++)
{
- regValue = dynamicKey.GetValue(i.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as byte[];
- if (regValue == null || regValue.Length != RegByteLength)
+ if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, i.ToString(CultureInfo.InvariantCulture), out dtzi))
{
- rules = null;
return false;
}
- dtzi = new REG_TZI_FORMAT(regValue);
AdjustmentRule middleRule = CreateAdjustmentRuleFromTimeZoneInformation(
dtzi,
new DateTime(i, 1, 1), // January 01, <Year>
}
// read the last year entry
- regValue = dynamicKey.GetValue(last.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as byte[];
- dtzi = new REG_TZI_FORMAT(regValue);
- if (regValue == null || regValue.Length != RegByteLength)
+ if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, last.ToString(CultureInfo.InvariantCulture), out dtzi))
{
- rules = null;
return false;
}
AdjustmentRule lastRule = CreateAdjustmentRuleFromTimeZoneInformation(
rulesList.Add(lastRule);
}
- // convert the ArrayList to an AdjustmentRule array
- rules = rulesList.ToArray();
- if (rules != null && rules.Length == 0)
+ // convert the List to an AdjustmentRule array
+ if (rulesList.Count != 0)
{
- rules = null;
+ rules = rulesList.ToArray();
}
} // end of: using (RegistryKey dynamicKey...
}
catch (InvalidCastException ex)
{
// one of the RegistryKey.GetValue calls could not be cast to an expected value type
- rules = null;
e = ex;
return false;
}
catch (ArgumentOutOfRangeException ex)
{
- rules = null;
e = ex;
return false;
}
catch (ArgumentException ex)
{
- rules = null;
e = ex;
return false;
}
return true;
}
+ private unsafe static bool TryGetTimeZoneEntryFromRegistry(RegistryKey key, string name, out REG_TZI_FORMAT dtzi)
+ {
+ byte[] regValue = key.GetValue(name, null, RegistryValueOptions.None) as byte[];
+ if (regValue == null || regValue.Length != sizeof(REG_TZI_FORMAT))
+ {
+ dtzi = default;
+ return false;
+ }
+ fixed (byte * pBytes = ®Value[0])
+ dtzi = *(REG_TZI_FORMAT *)pBytes;
+ return true;
+ }
+
/// <summary>
/// Helper function that compares the StandardBias and StandardDate portion a
/// TimeZoneInformation struct to a time zone registry entry.
private static bool TryCompareStandardDate(in TIME_ZONE_INFORMATION timeZone, in REG_TZI_FORMAT registryTimeZoneInfo) =>
timeZone.Bias == registryTimeZoneInfo.Bias &&
timeZone.StandardBias == registryTimeZoneInfo.StandardBias &&
- timeZone.StandardDate.Year == registryTimeZoneInfo.StandardDate.Year &&
- timeZone.StandardDate.Month == registryTimeZoneInfo.StandardDate.Month &&
- timeZone.StandardDate.DayOfWeek == registryTimeZoneInfo.StandardDate.DayOfWeek &&
- timeZone.StandardDate.Day == registryTimeZoneInfo.StandardDate.Day &&
- timeZone.StandardDate.Hour == registryTimeZoneInfo.StandardDate.Hour &&
- timeZone.StandardDate.Minute == registryTimeZoneInfo.StandardDate.Minute &&
- timeZone.StandardDate.Second == registryTimeZoneInfo.StandardDate.Second &&
- timeZone.StandardDate.Milliseconds == registryTimeZoneInfo.StandardDate.Milliseconds;
+ timeZone.StandardDate.Equals(registryTimeZoneInfo.StandardDate);
/// <summary>
/// Helper function that compares a TimeZoneInformation struct to a time zone registry entry.
}
REG_TZI_FORMAT registryTimeZoneInfo;
- byte[] regValue = key.GetValue(TimeZoneInfoValue, null, RegistryValueOptions.None) as byte[];
- if (regValue == null || regValue.Length != RegByteLength) return false;
- registryTimeZoneInfo = new REG_TZI_FORMAT(regValue);
+ if (!TryGetTimeZoneEntryFromRegistry(key, TimeZoneInfoValue, out registryTimeZoneInfo))
+ {
+ return false;
+ }
//
// first compare the bias and standard date information between the data from the Win32 API
// the Win32 API data and the registry data ...
//
(timeZone.DaylightBias == registryTimeZoneInfo.DaylightBias &&
- timeZone.DaylightDate.Year == registryTimeZoneInfo.DaylightDate.Year &&
- timeZone.DaylightDate.Month == registryTimeZoneInfo.DaylightDate.Month &&
- timeZone.DaylightDate.DayOfWeek == registryTimeZoneInfo.DaylightDate.DayOfWeek &&
- timeZone.DaylightDate.Day == registryTimeZoneInfo.DaylightDate.Day &&
- timeZone.DaylightDate.Hour == registryTimeZoneInfo.DaylightDate.Hour &&
- timeZone.DaylightDate.Minute == registryTimeZoneInfo.DaylightDate.Minute &&
- timeZone.DaylightDate.Second == registryTimeZoneInfo.DaylightDate.Second &&
- timeZone.DaylightDate.Milliseconds == registryTimeZoneInfo.DaylightDate.Milliseconds);
+ timeZone.DaylightDate.Equals(registryTimeZoneInfo.DaylightDate));
// Finally compare the "StandardName" string value...
//
if (result)
{
string registryStandardName = key.GetValue(StandardValue, string.Empty, RegistryValueOptions.None) as string;
- result = string.Equals(registryStandardName, timeZone.StandardName, StringComparison.Ordinal);
+ result = string.Equals(registryStandardName, timeZone.GetStandardName(), StringComparison.Ordinal);
}
return result;
}
try
{
StringBuilder fileMuiPath = StringBuilderCache.Acquire(Interop.Kernel32.MAX_PATH);
+ fileMuiPath.Length = Interop.Kernel32.MAX_PATH;
int fileMuiPathLength = Interop.Kernel32.MAX_PATH;
int languageLength = 0;
long enumerator = 0;
- bool succeeded = UnsafeNativeMethods.GetFileMUIPath(
- Win32Native.MUI_PREFERRED_UI_LANGUAGES,
+ bool succeeded = Interop.Kernel32.GetFileMUIPath(
+ Interop.Kernel32.MUI_PREFERRED_UI_LANGUAGES,
filePath, null /* language */, ref languageLength,
fileMuiPath, ref fileMuiPathLength, ref enumerator);
if (!succeeded)
/// resource dll(s). When the keys do not exist, the function falls back to reading from the standard
/// key-values
/// </summary>
- private static bool TryGetLocalizedNamesByRegistryKey(RegistryKey key, out string displayName, out string standardName, out string daylightName)
+ private static void GetLocalizedNamesByRegistryKey(RegistryKey key, out string displayName, out string standardName, out string daylightName)
{
displayName = string.Empty;
standardName = string.Empty;
{
daylightName = key.GetValue(DaylightValue, string.Empty, RegistryValueOptions.None) as string;
}
-
- return true;
}
/// <summary>
}
REG_TZI_FORMAT defaultTimeZoneInformation;
- byte[] regValue = key.GetValue(TimeZoneInfoValue, null, RegistryValueOptions.None) as byte[];
- if (regValue == null || regValue.Length != RegByteLength)
+ if (!TryGetTimeZoneEntryFromRegistry(key, TimeZoneInfoValue, out defaultTimeZoneInformation))
{
// the registry value could not be cast to a byte array
value = null;
return TimeZoneInfoResult.InvalidTimeZoneException;
}
- defaultTimeZoneInformation = new REG_TZI_FORMAT(regValue);
AdjustmentRule[] adjustmentRules;
if (!TryCreateAdjustmentRules(id, defaultTimeZoneInformation, out adjustmentRules, out e, defaultTimeZoneInformation.Bias))
return TimeZoneInfoResult.InvalidTimeZoneException;
}
- string displayName;
- string standardName;
- string daylightName;
-
- if (!TryGetLocalizedNamesByRegistryKey(key, out displayName, out standardName, out daylightName))
- {
- value = null;
- return TimeZoneInfoResult.InvalidTimeZoneException;
- }
+ GetLocalizedNamesByRegistryKey(key, out string displayName, out string standardName, out string daylightName);
try
{
internal static class UnsafeNativeMethods
{
- [DllImport(Interop.Libraries.Kernel32, EntryPoint = "GetTimeZoneInformation", SetLastError = true, ExactSpelling = true)]
- internal static extern int GetTimeZoneInformation(out Win32Native.TimeZoneInformation lpTimeZoneInformation);
-
- [DllImport(Interop.Libraries.Kernel32, EntryPoint = "GetDynamicTimeZoneInformation", SetLastError = true, ExactSpelling = true)]
- internal static extern int GetDynamicTimeZoneInformation(out Win32Native.DynamicTimeZoneInformation lpDynamicTimeZoneInformation);
-
- //
- // BOOL GetFileMUIPath(
- // DWORD dwFlags,
- // PCWSTR pcwszFilePath,
- // PWSTR pwszLanguage,
- // PULONG pcchLanguage,
- // PWSTR pwszFileMUIPath,
- // PULONG pcchFileMUIPath,
- // PULONGLONG pululEnumerator
- // );
- //
- [DllImport(Interop.Libraries.Kernel32, EntryPoint = "GetFileMUIPath", SetLastError = true, ExactSpelling = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static extern bool GetFileMUIPath(
- int flags,
- [MarshalAs(UnmanagedType.LPWStr)]
- String filePath,
- [MarshalAs(UnmanagedType.LPWStr)]
- StringBuilder language,
- ref int languageLength,
- [Out, MarshalAs(UnmanagedType.LPWStr)]
- StringBuilder fileMuiPath,
- ref int fileMuiPathLength,
- ref Int64 enumerator);
-
internal static unsafe class ManifestEtw
{
//
internal const int REG_RESOURCE_REQUIREMENTS_LIST = 10;
internal const int REG_QWORD = 11; // 64-bit number
- // TimeZone
- internal const int TIME_ZONE_ID_INVALID = -1;
- internal const int TIME_ZONE_ID_UNKNOWN = 0;
- internal const int TIME_ZONE_ID_STANDARD = 1;
- internal const int TIME_ZONE_ID_DAYLIGHT = 2;
- internal const int MAX_PATH = 260;
-
- internal const int MUI_LANGUAGE_ID = 0x4;
- internal const int MUI_LANGUAGE_NAME = 0x8;
- internal const int MUI_PREFERRED_UI_LANGUAGES = 0x10;
- internal const int MUI_INSTALLED_LANGUAGES = 0x20;
- internal const int MUI_ALL_LANGUAGES = 0x40;
- internal const int MUI_LANG_NEUTRAL_PE_FILE = 0x100;
- internal const int MUI_NON_LANG_NEUTRAL_FILE = 0x200;
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct SystemTime
- {
- [MarshalAs(UnmanagedType.U2)]
- public short Year;
- [MarshalAs(UnmanagedType.U2)]
- public short Month;
- [MarshalAs(UnmanagedType.U2)]
- public short DayOfWeek;
- [MarshalAs(UnmanagedType.U2)]
- public short Day;
- [MarshalAs(UnmanagedType.U2)]
- public short Hour;
- [MarshalAs(UnmanagedType.U2)]
- public short Minute;
- [MarshalAs(UnmanagedType.U2)]
- public short Second;
- [MarshalAs(UnmanagedType.U2)]
- public short Milliseconds;
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- internal struct TimeZoneInformation
- {
- [MarshalAs(UnmanagedType.I4)]
- public Int32 Bias;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
- public string StandardName;
- public SystemTime StandardDate;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 StandardBias;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
- public string DaylightName;
- public SystemTime DaylightDate;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 DaylightBias;
-
- public TimeZoneInformation(Win32Native.DynamicTimeZoneInformation dtzi)
- {
- Bias = dtzi.Bias;
- StandardName = dtzi.StandardName;
- StandardDate = dtzi.StandardDate;
- StandardBias = dtzi.StandardBias;
- DaylightName = dtzi.DaylightName;
- DaylightDate = dtzi.DaylightDate;
- DaylightBias = dtzi.DaylightBias;
- }
- }
-
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- internal struct DynamicTimeZoneInformation
- {
- [MarshalAs(UnmanagedType.I4)]
- public Int32 Bias;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
- public string StandardName;
- public SystemTime StandardDate;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 StandardBias;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
- public string DaylightName;
- public SystemTime DaylightDate;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 DaylightBias;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string TimeZoneKeyName;
- [MarshalAs(UnmanagedType.Bool)]
- public bool DynamicDaylightTimeDisabled;
- }
-
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct RegistryTimeZoneInformation
- {
- [MarshalAs(UnmanagedType.I4)]
- public Int32 Bias;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 StandardBias;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 DaylightBias;
- public SystemTime StandardDate;
- public SystemTime DaylightDate;
-
- public RegistryTimeZoneInformation(Win32Native.TimeZoneInformation tzi)
- {
- Bias = tzi.Bias;
- StandardDate = tzi.StandardDate;
- StandardBias = tzi.StandardBias;
- DaylightDate = tzi.DaylightDate;
- DaylightBias = tzi.DaylightBias;
- }
-
- public RegistryTimeZoneInformation(Byte[] bytes)
- {
- //
- // typedef struct _REG_TZI_FORMAT {
- // [00-03] LONG Bias;
- // [04-07] LONG StandardBias;
- // [08-11] LONG DaylightBias;
- // [12-27] SYSTEMTIME StandardDate;
- // [12-13] WORD wYear;
- // [14-15] WORD wMonth;
- // [16-17] WORD wDayOfWeek;
- // [18-19] WORD wDay;
- // [20-21] WORD wHour;
- // [22-23] WORD wMinute;
- // [24-25] WORD wSecond;
- // [26-27] WORD wMilliseconds;
- // [28-43] SYSTEMTIME DaylightDate;
- // [28-29] WORD wYear;
- // [30-31] WORD wMonth;
- // [32-33] WORD wDayOfWeek;
- // [34-35] WORD wDay;
- // [36-37] WORD wHour;
- // [38-39] WORD wMinute;
- // [40-41] WORD wSecond;
- // [42-43] WORD wMilliseconds;
- // } REG_TZI_FORMAT;
- //
- if (bytes == null || bytes.Length != 44)
- {
- throw new ArgumentException(SR.Argument_InvalidREG_TZI_FORMAT, nameof(bytes));
- }
- Bias = BitConverter.ToInt32(bytes, 0);
- StandardBias = BitConverter.ToInt32(bytes, 4);
- DaylightBias = BitConverter.ToInt32(bytes, 8);
-
- StandardDate.Year = BitConverter.ToInt16(bytes, 12);
- StandardDate.Month = BitConverter.ToInt16(bytes, 14);
- StandardDate.DayOfWeek = BitConverter.ToInt16(bytes, 16);
- StandardDate.Day = BitConverter.ToInt16(bytes, 18);
- StandardDate.Hour = BitConverter.ToInt16(bytes, 20);
- StandardDate.Minute = BitConverter.ToInt16(bytes, 22);
- StandardDate.Second = BitConverter.ToInt16(bytes, 24);
- StandardDate.Milliseconds = BitConverter.ToInt16(bytes, 26);
-
- DaylightDate.Year = BitConverter.ToInt16(bytes, 28);
- DaylightDate.Month = BitConverter.ToInt16(bytes, 30);
- DaylightDate.DayOfWeek = BitConverter.ToInt16(bytes, 32);
- DaylightDate.Day = BitConverter.ToInt16(bytes, 34);
- DaylightDate.Hour = BitConverter.ToInt16(bytes, 36);
- DaylightDate.Minute = BitConverter.ToInt16(bytes, 38);
- DaylightDate.Second = BitConverter.ToInt16(bytes, 40);
- DaylightDate.Milliseconds = BitConverter.ToInt16(bytes, 42);
- }
- }
-
- // end of TimeZone
-
-
// Win32 ACL-related constants:
internal const int READ_CONTROL = 0x00020000;
internal const int SYNCHRONIZE = 0x00100000;