Получение даты перевода часов. - C#
Формулировка задачи:
Здравствуйте, не получается получить правильный день перевода часов на летнее/стандартное время через WinAPI. Месяц возвращается верный, а день — нет.
GetTimeZoneInformation
SetTimeZoneInfomation
public static TimeZoneInformation GetTimeZoneInformation()
{
var tzi = new TimeZoneInformation();
Kernel.GetTimeZoneInformation(ref tzi);
// Установка параметров перевода (по докам MSDN)
tzi.StandardDate.wHour = 3;
tzi.StandardDate.wDayOfWeek = 4;
tzi.StandardDate.wMonth = 10;
tzi.StandardDate.wDay = 4;
tzi.DaylightDate.wHour = 2;
tzi.DaylightDate.wDayOfWeek = 0;
tzi.DaylightDate.wMonth = 4;
tzi.DaylightDate.wDay = 3;
// Сохранение данных перевода.
WinAPI.SetTimeZoneInfomation(tzi);
var info = new TimeZoneInformation();
Kernel.GetTimeZoneInformation(ref info);
// Структура с данными перевода часов.
return info;
}
public static void SetTimeZoneInfomation(TimeZoneInformation tzi)
{
// Установка привилегий.
var tkp = new TOKEN_PRIVILEGES
{
PrivilegeCount = 1,
Privileges = new LUID_AND_ATTRIBUTES[1] {
new LUID_AND_ATTRIBUTES { Attributes = SE_PRIVILEGE_ENABLED }
}
};
var hToken = new IntPtr();
Advapi.OpenProcessToken(Advapi.GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken);
Advapi.LookupPrivilegeValue("", SE_TIME_ZONE_NAME, out tkp.Privileges[0].Luid);
Advapi.AdjustTokenPrivileges(hToken, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);
// Установка даты.
Kernel.SetTimeZoneInformation(ref tzi);
// Сброс привилегий.
tkp.Privileges[0].Attributes = 0;
Advapi.AdjustTokenPrivileges(hToken, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);
}
class Kernel
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetTimeZoneInformation(ref TimeZoneInformation lpTimeZoneInformation);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool SetTimeZoneInformation(ref TimeZoneInformation lpTimeZoneInformation);
}
class Advapi
{
[DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, int BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
}Решение задачи: «Получение даты перевода часов.»
textual
Листинг программы
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Test
{
class Program
{
struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
[StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
struct TIME_ZONE_INFORMATION
{
public int Bias;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 32 )]
public string StandardName;
public SYSTEMTIME StandardDate;
public int StandardBias;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 32 )]
public string DaylightName;
public SYSTEMTIME DaylightDate;
public int DaylightBias;
}
[DllImport( "kernel32.dll", SetLastError = true )]
static extern uint GetTimeZoneInformation (
out TIME_ZONE_INFORMATION lpTimeZoneInformation
);
[DllImport( "kernel32.dll", SetLastError = true )]
[return: MarshalAs( UnmanagedType.Bool )]
static extern bool SetTimeZoneInformation (
ref TIME_ZONE_INFORMATION lpTimeZoneInformation
);
public static void Main ( ) {
Privileges.Enable( "SeTimeZonePrivilege" );
TIME_ZONE_INFORMATION tzi;
int err = 0;
GetTimeZoneInformation( out tzi );
tzi.StandardDate.wHour = 3;
tzi.StandardDate.wDayOfWeek = 4;
tzi.StandardDate.wMonth = 10;
tzi.StandardDate.wDay = 4;
tzi.DaylightDate.wHour = 2;
tzi.DaylightDate.wDayOfWeek = 0;
tzi.DaylightDate.wMonth = 4;
tzi.DaylightDate.wDay = 3;
if ( !SetTimeZoneInformation( ref tzi ) )
throw new Win32Exception( err = Marshal.GetLastWin32Error() );
GetTimeZoneInformation( out tzi );
// Меняется, при первом использовании, потом ясное дело - нет.
Debugger.Break();
}
}
class Privileges
{
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
struct TOKEN_PRIVILEGES
{
public uint PrivilegeCount;
public long Luid;
public uint Attributes;
}
[DllImport( "advapi32.dll", SetLastError = true )]
[return: MarshalAs( UnmanagedType.Bool )]
static extern bool AdjustTokenPrivileges ( IntPtr htok, bool disall,
ref TOKEN_PRIVILEGES newst, int len, IntPtr prev, IntPtr relen );
[DllImport( "kernel32.dll", SetLastError = true )]
static extern IntPtr GetCurrentProcess ( );
[DllImport( "advapi32.dll", SetLastError = true )]
[return: MarshalAs( UnmanagedType.Bool )]
static extern bool OpenProcessToken ( IntPtr h, int acc, ref IntPtr
phtok );
[DllImport( "advapi32.dll", SetLastError = true )]
[return: MarshalAs( UnmanagedType.Bool )]
static extern bool LookupPrivilegeValue ( string host, string name,
ref long pluid );
const int SE_PRIVILEGE_ENABLED = 0x00000002;
const int TOKEN_QUERY = 0x00000008;
const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
[DllImport( "kernel32.dll", SetLastError = true )]
[return: MarshalAs( UnmanagedType.Bool )]
static extern bool CloseHandle ( IntPtr hObject );
public static bool Enable ( string PrivName ) {
TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES();
IntPtr hToken = IntPtr.Zero;
bool retVal = false;
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken ) )
return false;
if ( LookupPrivilegeValue( null, PrivName, ref tp.Luid ) ) {
tp.PrivilegeCount = 1;
tp.Attributes = SE_PRIVILEGE_ENABLED;
retVal = AdjustTokenPrivileges( hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero );
}
CloseHandle( hToken );
return false;
}
}
}