/*++ Copyright (c) 1990 Microsoft Corporation Module Name: datetime.c Abstract: This module implements Win32 time of day functions Author: Mark Lucovsky (markl) 08-Oct-1990 Revision History: --*/ #include "basedll.h" #define IsActiveConsoleSession() (USER_SHARED_DATA->ActiveConsoleId == NtCurrentPeb()->SessionId) ULONG CalcClientTimeZoneIdAndBias( IN CONST TIME_ZONE_INFORMATION *ptzi, OUT KSYSTEM_TIME *pBias); BOOL IsTimeZoneRedirectionEnabled(); VOID WINAPI GetLocalTime( LPSYSTEMTIME lpLocalTime ) /*++ Routine Description: The current local system date and time can be returned using GetLocalTime. Arguments: lpLocalTime - Returns the current system date and time: SYSTEMTIME Structure: WORD wYear - Returns the current year. WORD wMonth - Returns the current month with January equal to 1. WORD wDayOfWeek - Returns the current day of the week where 0=Sunday, 1=Monday... WORD wDay - Returns the current day of the month. WORD wHour - Returns the current hour. WORD wMinute - Returns the current minute within the hour. WORD wSecond - Returns the current second within the minute. WORD wMilliseconds - Returns the current millisecond within the second. Return Value: None. --*/ { LARGE_INTEGER LocalTime; LARGE_INTEGER SystemTime; LARGE_INTEGER Bias; TIME_FIELDS TimeFields; volatile KSYSTEM_TIME *pRealBias; if(IsTimeZoneRedirectionEnabled()) { pRealBias=&(BaseStaticServerData->ktTermsrvClientBias); } else { pRealBias=&(USER_SHARED_DATA->TimeZoneBias); } // // Read system time from shared region. // do { SystemTime.HighPart = USER_SHARED_DATA->SystemTime.High1Time; SystemTime.LowPart = USER_SHARED_DATA->SystemTime.LowPart; } while (SystemTime.HighPart != USER_SHARED_DATA->SystemTime.High2Time); // // Read time zone bias from shared region. // If it's terminal server session use client bias. do { Bias.HighPart = pRealBias->High1Time; Bias.LowPart = pRealBias->LowPart; } while (Bias.HighPart != pRealBias->High2Time); LocalTime.QuadPart = SystemTime.QuadPart - Bias.QuadPart; RtlTimeToTimeFields(&LocalTime,&TimeFields); lpLocalTime->wYear = TimeFields.Year ; lpLocalTime->wMonth = TimeFields.Month ; lpLocalTime->wDayOfWeek = TimeFields.Weekday ; lpLocalTime->wDay = TimeFields.Day ; lpLocalTime->wHour = TimeFields.Hour ; lpLocalTime->wMinute = TimeFields.Minute ; lpLocalTime->wSecond = TimeFields.Second ; lpLocalTime->wMilliseconds = TimeFields.Milliseconds; } VOID WINAPI GetSystemTime( LPSYSTEMTIME lpSystemTime ) /*++ Routine Description: The current system date and time (UTC based) can be returned using GetSystemTime. Arguments: lpSystemTime - Returns the current system date and time: SYSTEMTIME Structure: WORD wYear - Returns the current year. WORD wMonth - Returns the current month with January equal to 1. WORD wDayOfWeek - Returns the current day of the week where 0=Sunday, 1=Monday... WORD wDay - Returns the current day of the month. WORD wHour - Returns the current hour. WORD wMinute - Returns the current minute within the hour. WORD wSecond - Returns the current second within the minute. WORD wMilliseconds - Returns the current millisecond within the second. Return Value: None. --*/ { LARGE_INTEGER SystemTime; TIME_FIELDS TimeFields; // // Read system time from shared region. // do { SystemTime.HighPart = USER_SHARED_DATA->SystemTime.High1Time; SystemTime.LowPart = USER_SHARED_DATA->SystemTime.LowPart; } while (SystemTime.HighPart != USER_SHARED_DATA->SystemTime.High2Time); RtlTimeToTimeFields(&SystemTime,&TimeFields); lpSystemTime->wYear = TimeFields.Year ; lpSystemTime->wMonth = TimeFields.Month ; lpSystemTime->wDayOfWeek = TimeFields.Weekday ; lpSystemTime->wDay = TimeFields.Day ; lpSystemTime->wHour = TimeFields.Hour ; lpSystemTime->wMinute = TimeFields.Minute ; lpSystemTime->wSecond = TimeFields.Second ; lpSystemTime->wMilliseconds = TimeFields.Milliseconds; } VOID WINAPI GetSystemTimeAsFileTime( LPFILETIME lpSystemTimeAsFileTime ) /*++ Routine Description: The current system date and time (UTC based) can be returned using GetSystemTimeAsFileTime. Arguments: lpSystemTimeAsFileTime - Returns the current system date and time formatted as a FILETIME structure Return Value: None. --*/ { LARGE_INTEGER SystemTime; // // Read system time from shared region. // do { SystemTime.HighPart = USER_SHARED_DATA->SystemTime.High1Time; SystemTime.LowPart = USER_SHARED_DATA->SystemTime.LowPart; } while (SystemTime.HighPart != USER_SHARED_DATA->SystemTime.High2Time); lpSystemTimeAsFileTime->dwLowDateTime = SystemTime.LowPart; lpSystemTimeAsFileTime->dwHighDateTime = SystemTime.HighPart; } BOOL WINAPI SetSystemTime( CONST SYSTEMTIME *lpSystemTime ) /*++ Routine Description: The current UTC based system date and time can be set using SetSystemTime. Arguments: lpSystemTime - Supplies the date and time to set. The wDayOfWeek field is ignored. Return Value: TRUE - The current system date and time was set. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { LARGE_INTEGER SystemTime; TIME_FIELDS TimeFields; BOOLEAN ReturnValue; PVOID State; NTSTATUS Status; ReturnValue = TRUE; TimeFields.Year = lpSystemTime->wYear ; TimeFields.Month = lpSystemTime->wMonth ; TimeFields.Day = lpSystemTime->wDay ; TimeFields.Hour = lpSystemTime->wHour ; TimeFields.Minute = lpSystemTime->wMinute ; TimeFields.Second = lpSystemTime->wSecond ; TimeFields.Milliseconds = lpSystemTime->wMilliseconds; if ( !RtlTimeFieldsToTime(&TimeFields,&SystemTime) ) { Status = STATUS_INVALID_PARAMETER; ReturnValue = FALSE; } else { Status = BasepAcquirePrivilegeEx( SE_SYSTEMTIME_PRIVILEGE, &State ); if ( NT_SUCCESS(Status) ) { Status = NtSetSystemTime(&SystemTime,NULL); BasepReleasePrivilege( State ); } if ( !NT_SUCCESS(Status) ) { ReturnValue = FALSE; } } if ( !ReturnValue ) { BaseSetLastNTError(Status); } return ReturnValue; } BOOL WINAPI SetLocalTime( CONST SYSTEMTIME *lpLocalTime ) /*++ Routine Description: The current local system date and time can be set using SetLocalTime. Arguments: lpSystemTime - Supplies the date and time to set. The wDayOfWeek field is ignored. Return Value: TRUE - The current system date and time was set. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { LARGE_INTEGER SystemTime; LARGE_INTEGER LocalTime; TIME_FIELDS TimeFields; BOOLEAN ReturnValue; PVOID State; NTSTATUS Status; LARGE_INTEGER Bias; volatile KSYSTEM_TIME *pRealBias; // // Read time zone bias from shared region. // If it's terminal server session use client bias. if(IsTimeZoneRedirectionEnabled()) { pRealBias=&(BaseStaticServerData->ktTermsrvClientBias); } else { pRealBias=&(USER_SHARED_DATA->TimeZoneBias); } do { Bias.HighPart = pRealBias->High1Time; Bias.LowPart = pRealBias->LowPart; } while (Bias.HighPart != pRealBias->High2Time); ReturnValue = TRUE; TimeFields.Year = lpLocalTime->wYear ; TimeFields.Month = lpLocalTime->wMonth ; TimeFields.Day = lpLocalTime->wDay ; TimeFields.Hour = lpLocalTime->wHour ; TimeFields.Minute = lpLocalTime->wMinute ; TimeFields.Second = lpLocalTime->wSecond ; TimeFields.Milliseconds = lpLocalTime->wMilliseconds; if ( !RtlTimeFieldsToTime(&TimeFields,&LocalTime) ) { Status = STATUS_INVALID_PARAMETER; ReturnValue = FALSE; } else { SystemTime.QuadPart = LocalTime.QuadPart + Bias.QuadPart; Status = BasepAcquirePrivilegeEx( SE_SYSTEMTIME_PRIVILEGE, &State ); if ( NT_SUCCESS(Status) ) { Status = NtSetSystemTime(&SystemTime,NULL); BasepReleasePrivilege( State ); if ( !NT_SUCCESS(Status) ) { ReturnValue = FALSE; } } else { ReturnValue = FALSE; } } if ( !ReturnValue ) { BaseSetLastNTError(Status); } return ReturnValue; } DWORD GetTickCount( VOID ) /*++ Routine Description: Win32 systems implement a free-running millisecond counter. The value of this counter can be read using GetTickCount. Arguments: None. Return Value: This function returns the number of milliseconds that have elapsed since the system was started. If the system has been running for a long time, it is possible that the count will repeat. The value of the counter is accurate within 55 milliseconds. --*/ { return (DWORD)NtGetTickCount(); } BOOL APIENTRY FileTimeToSystemTime( CONST FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime ) /*++ Routine Description: This functions converts a 64-bit file time value to a time in system time format. Arguments: lpFileTime - Supplies the 64-bit file time to convert to the system date and time format. lpSystemTime - Returns the converted value of the 64-bit file time. Return Value: TRUE - The 64-bit file time was successfully converted. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { LARGE_INTEGER FileTime; TIME_FIELDS TimeFields; FileTime.LowPart = lpFileTime->dwLowDateTime; FileTime.HighPart = lpFileTime->dwHighDateTime; if ( FileTime.QuadPart < 0 ) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } RtlTimeToTimeFields(&FileTime, &TimeFields); lpSystemTime->wYear = TimeFields.Year ; lpSystemTime->wMonth = TimeFields.Month ; lpSystemTime->wDay = TimeFields.Day ; lpSystemTime->wDayOfWeek = TimeFields.Weekday ; lpSystemTime->wHour = TimeFields.Hour ; lpSystemTime->wMinute = TimeFields.Minute ; lpSystemTime->wSecond = TimeFields.Second ; lpSystemTime->wMilliseconds = TimeFields.Milliseconds; return TRUE; } BOOL APIENTRY SystemTimeToFileTime( CONST SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime ) /*++ Routine Description: This functions converts a system time value into a 64-bit file time. Arguments: lpSystemTime - Supplies the time that is to be converted into the 64-bit file time format. The wDayOfWeek field is ignored. lpFileTime - Returns the 64-bit file time representation of lpSystemTime. Return Value: TRUE - The time was successfully converted. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { TIME_FIELDS TimeFields; LARGE_INTEGER FileTime; TimeFields.Year = lpSystemTime->wYear ; TimeFields.Month = lpSystemTime->wMonth ; TimeFields.Day = lpSystemTime->wDay ; TimeFields.Hour = lpSystemTime->wHour ; TimeFields.Minute = lpSystemTime->wMinute ; TimeFields.Second = lpSystemTime->wSecond ; TimeFields.Milliseconds = lpSystemTime->wMilliseconds; if ( !RtlTimeFieldsToTime(&TimeFields,&FileTime)) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } else { lpFileTime->dwLowDateTime = FileTime.LowPart; lpFileTime->dwHighDateTime = FileTime.HighPart; return TRUE; } } BOOL WINAPI FileTimeToLocalFileTime( CONST FILETIME *lpFileTime, LPFILETIME lpLocalFileTime ) /*++ Routine Description: This functions converts a UTC based file time to a local file time. Arguments: lpFileTime - Supplies the UTC based file time that is to be converted into a local file time lpLocalFileTime - Returns the 64-bit local file time representation of lpFileTime. Return Value: TRUE - The time was successfully converted. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { LARGE_INTEGER FileTime; LARGE_INTEGER LocalFileTime; LARGE_INTEGER Bias; volatile KSYSTEM_TIME *pRealBias; // // Read time zone bias from shared region. // If it's terminal server session use client bias. if(IsTimeZoneRedirectionEnabled()) { pRealBias=&(BaseStaticServerData->ktTermsrvClientBias); } else { pRealBias=&(USER_SHARED_DATA->TimeZoneBias); } do { Bias.HighPart = pRealBias->High1Time; Bias.LowPart = pRealBias->LowPart; } while (Bias.HighPart != pRealBias->High2Time); FileTime.LowPart = lpFileTime->dwLowDateTime; FileTime.HighPart = lpFileTime->dwHighDateTime; LocalFileTime.QuadPart = FileTime.QuadPart - Bias.QuadPart; lpLocalFileTime->dwLowDateTime = LocalFileTime.LowPart; lpLocalFileTime->dwHighDateTime = LocalFileTime.HighPart; return TRUE; } BOOL WINAPI LocalFileTimeToFileTime( CONST FILETIME *lpLocalFileTime, LPFILETIME lpFileTime ) /*++ Routine Description: This functions converts a local file time to a UTC based file time. Arguments: lpLocalFileTime - Supplies the local file time that is to be converted into a UTC based file time lpFileTime - Returns the 64-bit UTC based file time representation of lpLocalFileTime. Return Value: TRUE - The time was successfully converted. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { LARGE_INTEGER FileTime; LARGE_INTEGER LocalFileTime; LARGE_INTEGER Bias; volatile KSYSTEM_TIME *pRealBias; // // Read time zone bias from shared region. // If it's terminal server session use client bias. if(IsTimeZoneRedirectionEnabled()) { pRealBias=&(BaseStaticServerData->ktTermsrvClientBias); } else { pRealBias=&(USER_SHARED_DATA->TimeZoneBias); } do { Bias.HighPart = pRealBias->High1Time; Bias.LowPart = pRealBias->LowPart; } while (Bias.HighPart != pRealBias->High2Time); LocalFileTime.LowPart = lpLocalFileTime->dwLowDateTime; LocalFileTime.HighPart = lpLocalFileTime->dwHighDateTime; FileTime.QuadPart = LocalFileTime.QuadPart + Bias.QuadPart; lpFileTime->dwLowDateTime = FileTime.LowPart; lpFileTime->dwHighDateTime = FileTime.HighPart; return TRUE; } #define AlmostTwoSeconds (2*1000*1000*10 - 1) BOOL APIENTRY FileTimeToDosDateTime( CONST FILETIME *lpFileTime, LPWORD lpFatDate, LPWORD lpFatTime ) /*++ Routine Description: This function converts a 64-bit file time into DOS date and time value which is represented as two 16-bit unsigned integers. Since the DOS date format can only represent dates between 1/1/80 and 12/31/2107, this conversion can fail if the input file time is outside of this range. Arguments: lpFileTime - Supplies the 64-bit file time to convert to DOS date and time format. lpFatDate - Returns the 16-bit DOS representation of date. lpFatTime - Returns the 16-bit DOS representation of time. Return Value: TRUE - The file time was successfully converted. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { TIME_FIELDS TimeFields; LARGE_INTEGER FileTime; FileTime.LowPart = lpFileTime->dwLowDateTime; FileTime.HighPart = lpFileTime->dwHighDateTime; FileTime.QuadPart = FileTime.QuadPart + (LONGLONG)AlmostTwoSeconds; if ( FileTime.QuadPart < 0 ) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } RtlTimeToTimeFields(&FileTime, &TimeFields); if (TimeFields.Year < 1980 || TimeFields.Year > 2107) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } *lpFatDate = (WORD)( ((USHORT)(TimeFields.Year-(CSHORT)1980) << 9) | ((USHORT)TimeFields.Month << 5) | (USHORT)TimeFields.Day ); *lpFatTime = (WORD)( ((USHORT)TimeFields.Hour << 11) | ((USHORT)TimeFields.Minute << 5) | ((USHORT)TimeFields.Second >> 1) ); return TRUE; } BOOL APIENTRY DosDateTimeToFileTime( WORD wFatDate, WORD wFatTime, LPFILETIME lpFileTime ) /*++ Routine Description: This function converts a DOS date and time value, which is represented as two 16-bit unsigned integers, into a 64-bit file time. Arguments: lpFatDate - Supplies the 16-bit DOS representation of date. lpFatTime - Supplies the 16-bit DOS representation of time. lpFileTime - Returns the 64-bit file time converted from the DOS date and time format. Return Value: TRUE - The Dos date and time were successfully converted. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { TIME_FIELDS TimeFields; LARGE_INTEGER FileTime; TimeFields.Year = (CSHORT)((wFatDate & 0xFE00) >> 9)+(CSHORT)1980; TimeFields.Month = (CSHORT)((wFatDate & 0x01E0) >> 5); TimeFields.Day = (CSHORT)((wFatDate & 0x001F) >> 0); TimeFields.Hour = (CSHORT)((wFatTime & 0xF800) >> 11); TimeFields.Minute = (CSHORT)((wFatTime & 0x07E0) >> 5); TimeFields.Second = (CSHORT)((wFatTime & 0x001F) << 1); TimeFields.Milliseconds = 0; if (RtlTimeFieldsToTime(&TimeFields,&FileTime)) { lpFileTime->dwLowDateTime = FileTime.LowPart; lpFileTime->dwHighDateTime = FileTime.HighPart; return TRUE; } else { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } } LONG APIENTRY CompareFileTime( CONST FILETIME *lpFileTime1, CONST FILETIME *lpFileTime2 ) /*++ Routine Description: This function compares two 64-bit file times. Arguments: lpFileTime1 - pointer to a 64-bit file time. lpFileTime2 - pointer to a 64-bit file time. Return Value: -1 - *lpFileTime1 < *lpFileTime2 0 - *lpFileTime1 == *lpFileTime2 +1 - *lpFileTime1 > *lpFileTime2 --*/ { ULARGE_INTEGER FileTime1; ULARGE_INTEGER FileTime2; FileTime1.LowPart = lpFileTime1->dwLowDateTime; FileTime1.HighPart = lpFileTime1->dwHighDateTime; FileTime2.LowPart = lpFileTime2->dwLowDateTime; FileTime2.HighPart = lpFileTime2->dwHighDateTime; if (FileTime1.QuadPart < FileTime2.QuadPart) { return( -1 ); } else if (FileTime1.QuadPart > FileTime2.QuadPart) { return( 1 ); } else { return( 0 ); } } DWORD WINAPI GetTimeZoneInformation( LPTIME_ZONE_INFORMATION lpTimeZoneInformation ) /*++ Routine Description: This function allows an application to get the current timezone parameters These parameters control the Universal time to Local time translations. All UTC time to Local time translations are based on the following formula: UTC = LocalTime + Bias The return value of this function is the systems best guess of the current time zone parameters. This is one of: - Unknown - Standard Time - Daylight Savings Time If SetTimeZoneInformation was called without the transition date information, Unknown is returned, but the currect bias is used for local time translation. Otherwise, the system will correctly pick either daylight savings time or standard time. The information returned by this API is identical to the information stored in the last successful call to SetTimeZoneInformation. The exception is the Bias field returns the current Bias value in Arguments: lpTimeZoneInformation - Supplies the address of the time zone information structure. Return Value: TIME_ZONE_ID_UNKNOWN - The system can not determine the current timezone. This is usually due to a previous call to SetTimeZoneInformation where only the Bias was supplied and no transition dates were supplied. TIME_ZONE_ID_STANDARD - The system is operating in the range covered by StandardDate. TIME_ZONE_ID_DAYLIGHT - The system is operating in the range covered by DaylightDate. 0xffffffff - The operation failed. Extended error status is available using GetLastError. --*/ { RTL_TIME_ZONE_INFORMATION tzi; NTSTATUS Status; // // get the timezone data from the system // If it's terminal server session use client time zone if(IsTimeZoneRedirectionEnabled()) { *lpTimeZoneInformation = BaseStaticServerData->tziTermsrvClientTimeZone; return BaseStaticServerData->TermsrvClientTimeZoneId; } else { Status = NtQuerySystemInformation( SystemCurrentTimeZoneInformation, &tzi, sizeof(tzi), NULL ); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return 0xffffffff; } lpTimeZoneInformation->Bias = tzi.Bias; lpTimeZoneInformation->StandardBias = tzi.StandardBias; lpTimeZoneInformation->DaylightBias = tzi.DaylightBias; RtlCopyMemory(&lpTimeZoneInformation->StandardName,&tzi.StandardName,sizeof(tzi.StandardName)); RtlCopyMemory(&lpTimeZoneInformation->DaylightName,&tzi.DaylightName,sizeof(tzi.DaylightName)); lpTimeZoneInformation->StandardDate.wYear = tzi.StandardStart.Year ; lpTimeZoneInformation->StandardDate.wMonth = tzi.StandardStart.Month ; lpTimeZoneInformation->StandardDate.wDayOfWeek = tzi.StandardStart.Weekday ; lpTimeZoneInformation->StandardDate.wDay = tzi.StandardStart.Day ; lpTimeZoneInformation->StandardDate.wHour = tzi.StandardStart.Hour ; lpTimeZoneInformation->StandardDate.wMinute = tzi.StandardStart.Minute ; lpTimeZoneInformation->StandardDate.wSecond = tzi.StandardStart.Second ; lpTimeZoneInformation->StandardDate.wMilliseconds = tzi.StandardStart.Milliseconds; lpTimeZoneInformation->DaylightDate.wYear = tzi.DaylightStart.Year ; lpTimeZoneInformation->DaylightDate.wMonth = tzi.DaylightStart.Month ; lpTimeZoneInformation->DaylightDate.wDayOfWeek = tzi.DaylightStart.Weekday ; lpTimeZoneInformation->DaylightDate.wDay = tzi.DaylightStart.Day ; lpTimeZoneInformation->DaylightDate.wHour = tzi.DaylightStart.Hour ; lpTimeZoneInformation->DaylightDate.wMinute = tzi.DaylightStart.Minute ; lpTimeZoneInformation->DaylightDate.wSecond = tzi.DaylightStart.Second ; lpTimeZoneInformation->DaylightDate.wMilliseconds = tzi.DaylightStart.Milliseconds; return USER_SHARED_DATA->TimeZoneId; } } BOOL WINAPI SetTimeZoneInformation( CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation ) /*++ Routine Description: This function allows an application to set timezone parameters into their system. These parameters control the Universal time to Local time translations. All UTC time to Local time translations are based on the following formula: UTC = LocalTime + Bias This API allows the caller to program the current time zone bias, and optionally set up the system to automatically sense daylight savings time and standard time transitions. The timezone bias information is controlled by the TIME_ZONE_INFORMATION structure. Bias - Supplies the current bias in minutes for local time translation on this machine where LocalTime + Bias = UTC. This is a required filed of this structure. StandardName - Supplies an optional abbreviation string associated with standard time on this system. This string is uniterpreted and is supplied and used only by callers of this API and of GetTimeZoneInformation. StandardDate - Supplies an optional date and time (UTC) that describes the transition into standard time. A value of 0 in the wMonth field tells the system that StandardDate is not specified. If this field is specified, then DaylightDate must also be specified. Additionally, local time translations done during the StandardTime range will be done relative to the supplied StandardBias value (added to Bias). This field supports two date formats. Absolute form specifies and exact date and time when standard time begins. In this form, the wYear, wMonth, wDay, wHour, wMinute, wSecond, and wMilliseconds of the SYSTEMTIME structure are used to specify an exact date. Day-in-month time is specified by setting wYear to 0, setting wDayOfWeek to an appropriate weekday, and using wDay in the range of 1-5 to select the correct day in the month. Using this notation, the first sunday in april may be specified as can be the last thursday in october (5 is equal to "the last"). StandardBias - Supplies an optional bias value to be used during local time translations that occur during Standard Time. This field is ignored if StandardDate is not supplied. This bias value is added to the Bias field to form the Bias used during standard time. In most time zones, the value of this field is zero. DaylightName - Supplies an optional abbreviation string associated with daylight savings time on this system. This string is uniterpreted and is supplied and used only by callers of this API and of GetTimeZoneInformation. DaylightDate - Supplies an optional date and time (UTC) that describes the transition into daylight savings time. A value of 0 in the wMonth field tells the system that DaylightDate is not specified. If this field is specified, then StandardDate must also be specified. Additionally, local time translations done during the DaylightTime range will be done relative to the supplied DaylightBias value (added to Bias). The same dat formats supported by StandardDate are supported ib DaylightDate. DaylightBias - Supplies an optional bias value to be used during local time translations that occur during Daylight Savings Time. This field is ignored if DaylightDate is not supplied. This bias value is added to the Bias field to form the Bias used during daylight time. In most time zones, the value of this field is -60. Arguments: lpTimeZoneInformation - Supplies the address of the time zone information structure. Return Value: TRUE - The operation was successful. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { RTL_TIME_ZONE_INFORMATION tzi; NTSTATUS Status; if(IsTimeZoneRedirectionEnabled()) { return SetClientTimeZoneInformation(lpTimeZoneInformation); } else { tzi.Bias = lpTimeZoneInformation->Bias; tzi.StandardBias = lpTimeZoneInformation->StandardBias; tzi.DaylightBias = lpTimeZoneInformation->DaylightBias; RtlCopyMemory(&tzi.StandardName,&lpTimeZoneInformation->StandardName,sizeof(tzi.StandardName)); RtlCopyMemory(&tzi.DaylightName,&lpTimeZoneInformation->DaylightName,sizeof(tzi.DaylightName)); tzi.StandardStart.Year = lpTimeZoneInformation->StandardDate.wYear ; tzi.StandardStart.Month = lpTimeZoneInformation->StandardDate.wMonth ; tzi.StandardStart.Weekday = lpTimeZoneInformation->StandardDate.wDayOfWeek ; tzi.StandardStart.Day = lpTimeZoneInformation->StandardDate.wDay ; tzi.StandardStart.Hour = lpTimeZoneInformation->StandardDate.wHour ; tzi.StandardStart.Minute = lpTimeZoneInformation->StandardDate.wMinute ; tzi.StandardStart.Second = lpTimeZoneInformation->StandardDate.wSecond ; tzi.StandardStart.Milliseconds = lpTimeZoneInformation->StandardDate.wMilliseconds; tzi.DaylightStart.Year = lpTimeZoneInformation->DaylightDate.wYear ; tzi.DaylightStart.Month = lpTimeZoneInformation->DaylightDate.wMonth ; tzi.DaylightStart.Weekday = lpTimeZoneInformation->DaylightDate.wDayOfWeek ; tzi.DaylightStart.Day = lpTimeZoneInformation->DaylightDate.wDay ; tzi.DaylightStart.Hour = lpTimeZoneInformation->DaylightDate.wHour ; tzi.DaylightStart.Minute = lpTimeZoneInformation->DaylightDate.wMinute ; tzi.DaylightStart.Second = lpTimeZoneInformation->DaylightDate.wSecond ; tzi.DaylightStart.Milliseconds = lpTimeZoneInformation->DaylightDate.wMilliseconds; Status = RtlSetTimeZoneInformation( &tzi ); if (!NT_SUCCESS( Status )) { BaseSetLastNTError(Status); return FALSE; } // // Refresh the system's concept of time // NtSetSystemTime(NULL,NULL); return TRUE; } } BOOL WINAPI GetSystemTimeAdjustment( PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement, PBOOL lpTimeAdjustmentDisabled ) /*++ Routine Description: This function is used to support algorithms that want to synchronize the time of day (reported via GetSystemTime and GetLocalTime) with another time source using a programmed clock adjustment over a period of time. To facilitate this, the system computes the time of day by adding a value to a time of day counter at a periodic interval. This API allows the caller to obtain the periodic interval (clock interrupt rate), and the amount added to the time of day with each interrupt. A boolean value is also returned which indicates whether or not this time adjustment algorithm is even being used. A value of TRUE indicates that adjustment is not being used. If this is the case, the system may attempt to keep the time of day clock in sync using its own internal mechanisms. This may cause time of day to periodicly "jump" to the "correct time". Arguments: lpTimeAdjustment - Returns the number of 100ns units added to the time of day counter at each clock interrupt. lpTimeIncrement - Returns the clock interrupt rate in 100ns units. lpTimeAdjustmentDisabled - Returns an indicator which specifies whether or not time adjustment is inabled. A value of TRUE indicates that periodic adjustment is disabled (*lpTimeAdjustment == *lpTimeIncrement), AND that the system is free to serialize time of day using any mechanism it wants. This may cause periodic time jumps as the system serializes time of day to the "correct time". A value of false indicates that programmed time adjustment is being used to serialize the time of day, and that the system will not interfere with this scheme and will not attempt to synchronize time of day on its own. Return Value: TRUE - The operation was successful. FALSE - The operation failed. Use GetLastError to obtain detailed error information. --*/ { NTSTATUS Status; SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeAdjust; BOOL b; Status = NtQuerySystemInformation( SystemTimeAdjustmentInformation, &TimeAdjust, sizeof(TimeAdjust), NULL ); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); b = FALSE; } else { *lpTimeAdjustment = TimeAdjust.TimeAdjustment; *lpTimeIncrement = TimeAdjust.TimeIncrement; *lpTimeAdjustmentDisabled = TimeAdjust.Enable; b = TRUE; } return b; } BOOL WINAPI SetSystemTimeAdjustment( DWORD dwTimeAdjustment, BOOL bTimeAdjustmentDisabled ) /*++ Routine Description: This function is used to tell the system the parameters it should use to periodicaly synchronize time of day with some other source. This API supports two modes of operation. In the first mode, bTimeAdjustmentDisabled is set to FALSE. At each clock interrupt, the value of dwTimeAdjustment is added to the time of day. The clock interrupt rate may be obtained using GetSystemTimeAdjustment, and looking at the returned value of lpTimeIncrement. In the second mode, bTimeAdjustmentDisabled is set to TRUE. At each clock interrupt, the clock interrupt rate is added to the time of day. The system may also periodically refresh the time of day using other internal algorithms. These may produce "jumps" in time. The application must have system-time privilege (the SE_SYSTEMTIME_NAME privilege) for this function to succeed. This privilege is disabled by default. Use the AdjustTokenPrivileges function to enable the privilege and again to disable it after the time adjustment has been set. Arguments: dwTimeAdjustment - Supplies the value (in 100ns units) that is to be added to the time of day at each clock interrupt. bTimeAdjustmentDisabled - Supplies a flag which specifies the time adjustment mode that the system is to use. A value of TRUE indicates the the system should synchronize time of day using its own internal mechanisms. When this is the case, the value of dwTimeAdjustment is ignored. A value of FALSE indicates that the application is in control, and that the value specified by dwTimeAdjustment is to be added to the time of day at each clock interrupt. Return Value: TRUE - The operation was successful. FALSE - The operation failed. Use GetLastError to obtain detailed error information. --*/ { NTSTATUS Status; SYSTEM_SET_TIME_ADJUST_INFORMATION TimeAdjust; BOOL b; b = TRUE; TimeAdjust.TimeAdjustment = dwTimeAdjustment; TimeAdjust.Enable = (BOOLEAN)bTimeAdjustmentDisabled; Status = NtSetSystemInformation( SystemTimeAdjustmentInformation, &TimeAdjust, sizeof(TimeAdjust) ); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); b = FALSE; } return b; } BOOL WINAPI SystemTimeToTzSpecificLocalTime( LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpUniversalTime, LPSYSTEMTIME lpLocalTime ) { TIME_ZONE_INFORMATION TziData; LPTIME_ZONE_INFORMATION Tzi; RTL_TIME_ZONE_INFORMATION tzi; LARGE_INTEGER TimeZoneBias; LARGE_INTEGER NewTimeZoneBias; LARGE_INTEGER LocalCustomBias; LARGE_INTEGER StandardTime; LARGE_INTEGER DaylightTime; LARGE_INTEGER UtcStandardTime; LARGE_INTEGER UtcDaylightTime; LARGE_INTEGER CurrentUniversalTime; LARGE_INTEGER ComputedLocalTime; ULONG CurrentTimeZoneId = 0xffffffff; // // Get the timezone information into a useful format // if ( !ARGUMENT_PRESENT(lpTimeZoneInformation) ) { // // Convert universal time to local time using current timezone info // if (GetTimeZoneInformation(&TziData) == TIME_ZONE_ID_INVALID) { return FALSE; } Tzi = &TziData; } else { Tzi = lpTimeZoneInformation; } tzi.Bias = Tzi->Bias; tzi.StandardBias = Tzi->StandardBias; tzi.DaylightBias = Tzi->DaylightBias; RtlCopyMemory(&tzi.StandardName,&Tzi->StandardName,sizeof(tzi.StandardName)); RtlCopyMemory(&tzi.DaylightName,&Tzi->DaylightName,sizeof(tzi.DaylightName)); tzi.StandardStart.Year = Tzi->StandardDate.wYear ; tzi.StandardStart.Month = Tzi->StandardDate.wMonth ; tzi.StandardStart.Weekday = Tzi->StandardDate.wDayOfWeek ; tzi.StandardStart.Day = Tzi->StandardDate.wDay ; tzi.StandardStart.Hour = Tzi->StandardDate.wHour ; tzi.StandardStart.Minute = Tzi->StandardDate.wMinute ; tzi.StandardStart.Second = Tzi->StandardDate.wSecond ; tzi.StandardStart.Milliseconds = Tzi->StandardDate.wMilliseconds; tzi.DaylightStart.Year = Tzi->DaylightDate.wYear ; tzi.DaylightStart.Month = Tzi->DaylightDate.wMonth ; tzi.DaylightStart.Weekday = Tzi->DaylightDate.wDayOfWeek ; tzi.DaylightStart.Day = Tzi->DaylightDate.wDay ; tzi.DaylightStart.Hour = Tzi->DaylightDate.wHour ; tzi.DaylightStart.Minute = Tzi->DaylightDate.wMinute ; tzi.DaylightStart.Second = Tzi->DaylightDate.wSecond ; tzi.DaylightStart.Milliseconds = Tzi->DaylightDate.wMilliseconds; // // convert the input universal time to NT style time // if ( !SystemTimeToFileTime(lpUniversalTime,(LPFILETIME)&CurrentUniversalTime) ) { return FALSE; } // // Get the new timezone bias // NewTimeZoneBias.QuadPart = Int32x32To64(tzi.Bias*60, 10000000); // // Now see if we have stored cutover times // if ( tzi.StandardStart.Month && tzi.DaylightStart.Month ) { // // We have timezone cutover information. Compute the // cutover dates and compute what our current bias // is // if ( !RtlCutoverTimeToSystemTime( &tzi.StandardStart, &StandardTime, &CurrentUniversalTime, TRUE ) ) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } if ( !RtlCutoverTimeToSystemTime( &tzi.DaylightStart, &DaylightTime, &CurrentUniversalTime, TRUE ) ) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } // // Convert standard time and daylight time to utc // LocalCustomBias.QuadPart = Int32x32To64(tzi.StandardBias*60, 10000000); TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart; UtcDaylightTime.QuadPart = DaylightTime.QuadPart + TimeZoneBias.QuadPart; LocalCustomBias.QuadPart = Int32x32To64(tzi.DaylightBias*60, 10000000); TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart; UtcStandardTime.QuadPart = StandardTime.QuadPart + TimeZoneBias.QuadPart; // // If daylight < standard, then time >= daylight and // less than standard is daylight // if ( UtcDaylightTime.QuadPart < UtcStandardTime.QuadPart ) { // // If today is >= DaylightTime and < StandardTime, then // We are in daylight savings time // if ( (CurrentUniversalTime.QuadPart >= UtcDaylightTime.QuadPart) && (CurrentUniversalTime.QuadPart < UtcStandardTime.QuadPart) ) { CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; } else { CurrentTimeZoneId = TIME_ZONE_ID_STANDARD; } } else { // // If today is >= StandardTime and < DaylightTime, then // We are in standard time // if ( (CurrentUniversalTime.QuadPart >= UtcStandardTime.QuadPart ) && (CurrentUniversalTime.QuadPart < UtcDaylightTime.QuadPart ) ) { CurrentTimeZoneId = TIME_ZONE_ID_STANDARD; } else { CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; } } // // At this point, we know our current timezone and the // Universal time of the next cutover. // LocalCustomBias.QuadPart = Int32x32To64( CurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ? tzi.DaylightBias*60 : tzi.StandardBias*60, // Bias in seconds 10000000 ); TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart; } else { TimeZoneBias = NewTimeZoneBias; } ComputedLocalTime.QuadPart = CurrentUniversalTime.QuadPart - TimeZoneBias.QuadPart; if ( !FileTimeToSystemTime((LPFILETIME)&ComputedLocalTime,lpLocalTime) ) { return FALSE; } return TRUE; } BOOL WINAPI TzSpecificLocalTimeToSystemTime( LPTIME_ZONE_INFORMATION lpTimeZoneInformation, LPSYSTEMTIME lpLocalTime, LPSYSTEMTIME lpUniversalTime ) { TIME_ZONE_INFORMATION TziData; LPTIME_ZONE_INFORMATION Tzi; RTL_TIME_ZONE_INFORMATION tzi; LARGE_INTEGER TimeZoneBias; LARGE_INTEGER NewTimeZoneBias; LARGE_INTEGER LocalCustomBias; LARGE_INTEGER StandardTime; LARGE_INTEGER DaylightTime; LARGE_INTEGER CurrentLocalTime; LARGE_INTEGER ComputedUniversalTime; ULONG CurrentTimeZoneId = 0xffffffff; // // Get the timezone information into a useful format // if ( !ARGUMENT_PRESENT(lpTimeZoneInformation) ) { // // Convert universal time to local time using current timezone info // if (GetTimeZoneInformation(&TziData) == TIME_ZONE_ID_INVALID) { return FALSE; } Tzi = &TziData; } else { Tzi = lpTimeZoneInformation; } tzi.Bias = Tzi->Bias; tzi.StandardBias = Tzi->StandardBias; tzi.DaylightBias = Tzi->DaylightBias; RtlCopyMemory(&tzi.StandardName,&Tzi->StandardName,sizeof(tzi.StandardName)); RtlCopyMemory(&tzi.DaylightName,&Tzi->DaylightName,sizeof(tzi.DaylightName)); tzi.StandardStart.Year = Tzi->StandardDate.wYear ; tzi.StandardStart.Month = Tzi->StandardDate.wMonth ; tzi.StandardStart.Weekday = Tzi->StandardDate.wDayOfWeek ; tzi.StandardStart.Day = Tzi->StandardDate.wDay ; tzi.StandardStart.Hour = Tzi->StandardDate.wHour ; tzi.StandardStart.Minute = Tzi->StandardDate.wMinute ; tzi.StandardStart.Second = Tzi->StandardDate.wSecond ; tzi.StandardStart.Milliseconds = Tzi->StandardDate.wMilliseconds; tzi.DaylightStart.Year = Tzi->DaylightDate.wYear ; tzi.DaylightStart.Month = Tzi->DaylightDate.wMonth ; tzi.DaylightStart.Weekday = Tzi->DaylightDate.wDayOfWeek ; tzi.DaylightStart.Day = Tzi->DaylightDate.wDay ; tzi.DaylightStart.Hour = Tzi->DaylightDate.wHour ; tzi.DaylightStart.Minute = Tzi->DaylightDate.wMinute ; tzi.DaylightStart.Second = Tzi->DaylightDate.wSecond ; tzi.DaylightStart.Milliseconds = Tzi->DaylightDate.wMilliseconds; // // convert the input local time to NT style time // if ( !SystemTimeToFileTime(lpLocalTime,(LPFILETIME)&CurrentLocalTime) ) { return FALSE; } // // Get the new timezone bias // NewTimeZoneBias.QuadPart = Int32x32To64(tzi.Bias*60, 10000000); // // Now see if we have stored cutover times // if ( tzi.StandardStart.Month && tzi.DaylightStart.Month ) { // // We have timezone cutover information. Compute the // cutover dates and compute what our current bias // is // if ( !RtlCutoverTimeToSystemTime( &tzi.StandardStart, &StandardTime, &CurrentLocalTime, TRUE ) ) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } if ( !RtlCutoverTimeToSystemTime( &tzi.DaylightStart, &DaylightTime, &CurrentLocalTime, TRUE ) ) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } // // If daylight < standard, then time >= daylight and // less than standard is daylight // if ( DaylightTime.QuadPart < StandardTime.QuadPart ) { // // If today is >= DaylightTime and < StandardTime, then // We are in daylight savings time // if ( (CurrentLocalTime.QuadPart >= DaylightTime.QuadPart) && (CurrentLocalTime.QuadPart < StandardTime.QuadPart) ) { CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; } else { CurrentTimeZoneId = TIME_ZONE_ID_STANDARD; } } else { // // If today is >= StandardTime and < DaylightTime, then // We are in standard time // if ( (CurrentLocalTime.QuadPart >= StandardTime.QuadPart ) && (CurrentLocalTime.QuadPart < DaylightTime.QuadPart ) ) { CurrentTimeZoneId = TIME_ZONE_ID_STANDARD; } else { CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; } } // // At this point, we know our current timezone and the // local time of the next cutover. // LocalCustomBias.QuadPart = Int32x32To64( CurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ? tzi.DaylightBias*60 : tzi.StandardBias*60, // Bias in seconds 10000000 ); TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart; } else { TimeZoneBias = NewTimeZoneBias; } ComputedUniversalTime.QuadPart = CurrentLocalTime.QuadPart + TimeZoneBias.QuadPart; if ( !FileTimeToSystemTime((LPFILETIME)&ComputedUniversalTime,lpUniversalTime) ) { return FALSE; } return TRUE; } BOOL WINAPI SetClientTimeZoneInformation( IN CONST TIME_ZONE_INFORMATION *ptzi ) /*++ Routine Description: Sets information in global structures used to calculate local time in TS session. Arguments: IN CONST TIME_ZONE_INFORMATION *ptzi Return Value: TRUE - The operation was successful. FALSE - The operation failed. Use GetLastError to obtain detailed error information. Client time zone information may become invalid during this call In this case we will use time zone information from server --*/ { NTSTATUS Status; BASE_API_MSG m; PBASE_SET_TERMSRVCLIENTTIMEZONE c = &m.u.SetTermsrvClientTimeZone; c->fFirstChunk=TRUE; //this meanes that this is only first portion of data //we have to cut it ito two pieces because of //message size restrictions (100 bytes) c->Bias=ptzi->Bias; RtlCopyMemory(&c->Name,&ptzi->StandardName,sizeof(ptzi->StandardName)); c->Date=ptzi->StandardDate; c->Bias1=ptzi->StandardBias; #if defined(BUILD_WOW6432) Status = CsrBasepSetClientTimeZoneInformation(c); #else Status = CsrClientCallServer((PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetTermsrvClientTimeZone), sizeof( *c )); #endif if ( !NT_SUCCESS( Status ) ) { SetLastError( RtlNtStatusToDosError( Status ) ); return( FALSE ); } c->fFirstChunk=FALSE; //this is a second and last portion of data RtlCopyMemory(&c->Name,&ptzi->DaylightName,sizeof(ptzi->DaylightName)); c->Date=ptzi->DaylightDate; c->Bias1=ptzi->DaylightBias; c->TimeZoneId=CalcClientTimeZoneIdAndBias(ptzi,&c->RealBias); #if defined(BUILD_WOW6432) Status = CsrBasepSetClientTimeZoneInformation(c); #else Status = CsrClientCallServer((PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetTermsrvClientTimeZone), sizeof( *c )); #endif if ( !NT_SUCCESS( Status ) ) { SetLastError( RtlNtStatusToDosError( Status ) ); return( FALSE ); } return( TRUE ); } ULONG CalcClientTimeZoneIdAndBias( IN CONST TIME_ZONE_INFORMATION *ptzi, OUT KSYSTEM_TIME *pBias) /*++ Routine Description: Calculates current bias and time zone ID. Arguments: IN CONST TIME_ZONE_INFORMATION *ptzi - time zone for which to calculate bias OUT KSYSTEM_TIME *pBias - current bias Return Value: TIME_ZONE_ID_UNKNOWN - daylight saving time is not used in the current time zone. TIME_ZONE_ID_STANDARD - The system is operating in the range covered by StandardDate. TIME_ZONE_ID_DAYLIGHT - The system is operating in the range covered by DaylightDate. TIME_ZONE_ID_INVALID - The operation failed. Extended error status is available using GetLastError. --*/ { LARGE_INTEGER TimeZoneBias; LARGE_INTEGER NewTimeZoneBias; LARGE_INTEGER LocalCustomBias; LARGE_INTEGER StandardTime; LARGE_INTEGER DaylightTime; LARGE_INTEGER UtcStandardTime; LARGE_INTEGER UtcDaylightTime; SYSTEMTIME CurrentSystemTime; LARGE_INTEGER CurrentUniversalTime; ULONG CurrentTimeZoneId = 0xffffffff; TIME_FIELDS StandardStart,DaylightStart; NewTimeZoneBias.QuadPart = Int32x32To64(ptzi->Bias*60, 10000000); // // Now see if we have stored cutover times // if ( ptzi->StandardDate.wMonth && ptzi->DaylightDate.wMonth ) { GetSystemTime(&CurrentSystemTime); SystemTimeToFileTime(&CurrentSystemTime,(LPFILETIME)&CurrentUniversalTime); StandardStart.Year = ptzi->StandardDate.wYear ; StandardStart.Month = ptzi->StandardDate.wMonth ; StandardStart.Weekday = ptzi->StandardDate.wDayOfWeek ; StandardStart.Day = ptzi->StandardDate.wDay ; StandardStart.Hour = ptzi->StandardDate.wHour ; StandardStart.Minute = ptzi->StandardDate.wMinute ; StandardStart.Second = ptzi->StandardDate.wSecond ; StandardStart.Milliseconds = ptzi->StandardDate.wMilliseconds; DaylightStart.Year = ptzi->DaylightDate.wYear ; DaylightStart.Month = ptzi->DaylightDate.wMonth ; DaylightStart.Weekday = ptzi->DaylightDate.wDayOfWeek ; DaylightStart.Day = ptzi->DaylightDate.wDay ; DaylightStart.Hour = ptzi->DaylightDate.wHour ; DaylightStart.Minute = ptzi->DaylightDate.wMinute ; DaylightStart.Second = ptzi->DaylightDate.wSecond ; DaylightStart.Milliseconds = ptzi->DaylightDate.wMilliseconds; // // We have timezone cutover information. Compute the // cutover dates and compute what our current bias // is // if((!RtlCutoverTimeToSystemTime(&StandardStart,&StandardTime, &CurrentUniversalTime,TRUE)) || (!RtlCutoverTimeToSystemTime(&DaylightStart,&DaylightTime, &CurrentUniversalTime,TRUE))) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return TIME_ZONE_ID_INVALID; } // // Convert standard time and daylight time to utc // LocalCustomBias.QuadPart = Int32x32To64(ptzi->StandardBias*60, 10000000); TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart; UtcDaylightTime.QuadPart = DaylightTime.QuadPart + TimeZoneBias.QuadPart; LocalCustomBias.QuadPart = Int32x32To64(ptzi->DaylightBias*60, 10000000); TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart; UtcStandardTime.QuadPart = StandardTime.QuadPart + TimeZoneBias.QuadPart; // // If daylight < standard, then time >= daylight and // less than standard is daylight // if ( UtcDaylightTime.QuadPart < UtcStandardTime.QuadPart ) { // // If today is >= DaylightTime and < StandardTime, then // We are in daylight savings time // if ( (CurrentUniversalTime.QuadPart >= UtcDaylightTime.QuadPart) && (CurrentUniversalTime.QuadPart < UtcStandardTime.QuadPart) ) { CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; } else { CurrentTimeZoneId = TIME_ZONE_ID_STANDARD; } } else { // // If today is >= StandardTime and < DaylightTime, then // We are in standard time // if ( (CurrentUniversalTime.QuadPart >= UtcStandardTime.QuadPart ) && (CurrentUniversalTime.QuadPart < UtcDaylightTime.QuadPart ) ) { CurrentTimeZoneId = TIME_ZONE_ID_STANDARD; } else { CurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; } } // // At this point, we know our current timezone and the // Universal time of the next cutover. // LocalCustomBias.QuadPart = Int32x32To64( CurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ? ptzi->DaylightBias*60 : ptzi->StandardBias*60, // Bias in seconds 10000000 ); TimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart; } else { TimeZoneBias = NewTimeZoneBias; CurrentTimeZoneId=TIME_ZONE_ID_UNKNOWN; } pBias->LowPart=(ULONG)(TimeZoneBias.LowPart); pBias->High1Time=pBias->High2Time=(LONG)(TimeZoneBias.HighPart); return CurrentTimeZoneId; } BOOL IsTimeZoneRedirectionEnabled() { /*++ Routine Description: Checks if all conditions are met to allow Time Zone redirection on the TS session. Arguments: NONE Return Value: TRUE - if we allowed to do TZ redirection. --*/ return (BaseStaticServerData->TermsrvClientTimeZoneId != TIME_ZONE_ID_INVALID); } /* //These 2 functions will be needed for new timedate.cpl DWORD WINAPI GetServerTimeZoneInformation( LPTIME_ZONE_INFORMATION lpTimeZoneInformation ) { RTL_TIME_ZONE_INFORMATION tzi; NTSTATUS Status; // // get the timezone data from the system // Status = NtQuerySystemInformation( SystemCurrentTimeZoneInformation, &tzi, sizeof(tzi), NULL ); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return 0xffffffff; } lpTimeZoneInformation->Bias = tzi.Bias; lpTimeZoneInformation->StandardBias = tzi.StandardBias; lpTimeZoneInformation->DaylightBias = tzi.DaylightBias; RtlCopyMemory(&lpTimeZoneInformation->StandardName,&tzi.StandardName,sizeof(tzi.StandardName)); RtlCopyMemory(&lpTimeZoneInformation->DaylightName,&tzi.DaylightName,sizeof(tzi.DaylightName)); lpTimeZoneInformation->StandardDate.wYear = tzi.StandardStart.Year ; lpTimeZoneInformation->StandardDate.wMonth = tzi.StandardStart.Month ; lpTimeZoneInformation->StandardDate.wDayOfWeek = tzi.StandardStart.Weekday ; lpTimeZoneInformation->StandardDate.wDay = tzi.StandardStart.Day ; lpTimeZoneInformation->StandardDate.wHour = tzi.StandardStart.Hour ; lpTimeZoneInformation->StandardDate.wMinute = tzi.StandardStart.Minute ; lpTimeZoneInformation->StandardDate.wSecond = tzi.StandardStart.Second ; lpTimeZoneInformation->StandardDate.wMilliseconds = tzi.StandardStart.Milliseconds; lpTimeZoneInformation->DaylightDate.wYear = tzi.DaylightStart.Year ; lpTimeZoneInformation->DaylightDate.wMonth = tzi.DaylightStart.Month ; lpTimeZoneInformation->DaylightDate.wDayOfWeek = tzi.DaylightStart.Weekday ; lpTimeZoneInformation->DaylightDate.wDay = tzi.DaylightStart.Day ; lpTimeZoneInformation->DaylightDate.wHour = tzi.DaylightStart.Hour ; lpTimeZoneInformation->DaylightDate.wMinute = tzi.DaylightStart.Minute ; lpTimeZoneInformation->DaylightDate.wSecond = tzi.DaylightStart.Second ; lpTimeZoneInformation->DaylightDate.wMilliseconds = tzi.DaylightStart.Milliseconds; return USER_SHARED_DATA->TimeZoneId; } BOOL WINAPI SetServerTimeZoneInformation( CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation ) { RTL_TIME_ZONE_INFORMATION tzi; NTSTATUS Status; tzi.Bias = lpTimeZoneInformation->Bias; tzi.StandardBias = lpTimeZoneInformation->StandardBias; tzi.DaylightBias = lpTimeZoneInformation->DaylightBias; RtlCopyMemory(&tzi.StandardName,&lpTimeZoneInformation->StandardName,sizeof(tzi.StandardName)); RtlCopyMemory(&tzi.DaylightName,&lpTimeZoneInformation->DaylightName,sizeof(tzi.DaylightName)); tzi.StandardStart.Year = lpTimeZoneInformation->StandardDate.wYear ; tzi.StandardStart.Month = lpTimeZoneInformation->StandardDate.wMonth ; tzi.StandardStart.Weekday = lpTimeZoneInformation->StandardDate.wDayOfWeek ; tzi.StandardStart.Day = lpTimeZoneInformation->StandardDate.wDay ; tzi.StandardStart.Hour = lpTimeZoneInformation->StandardDate.wHour ; tzi.StandardStart.Minute = lpTimeZoneInformation->StandardDate.wMinute ; tzi.StandardStart.Second = lpTimeZoneInformation->StandardDate.wSecond ; tzi.StandardStart.Milliseconds = lpTimeZoneInformation->StandardDate.wMilliseconds; tzi.DaylightStart.Year = lpTimeZoneInformation->DaylightDate.wYear ; tzi.DaylightStart.Month = lpTimeZoneInformation->DaylightDate.wMonth ; tzi.DaylightStart.Weekday = lpTimeZoneInformation->DaylightDate.wDayOfWeek ; tzi.DaylightStart.Day = lpTimeZoneInformation->DaylightDate.wDay ; tzi.DaylightStart.Hour = lpTimeZoneInformation->DaylightDate.wHour ; tzi.DaylightStart.Minute = lpTimeZoneInformation->DaylightDate.wMinute ; tzi.DaylightStart.Second = lpTimeZoneInformation->DaylightDate.wSecond ; tzi.DaylightStart.Milliseconds = lpTimeZoneInformation->DaylightDate.wMilliseconds; Status = RtlSetTimeZoneInformation( &tzi ); if (!NT_SUCCESS( Status )) { BaseSetLastNTError(Status); return FALSE; } // // Refresh the system's concept of time // NtSetSystemTime(NULL,NULL); return TRUE; } */