windows-nt/Source/XPSP1/NT/termsrv/remdsk/server/sessmgr/mktime.cpp

269 lines
7.6 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "stdafx.h"
#include <windows.h>
#include "helper.h"
///////////////////////////////////////////////////////////////////////////////
//
// Portion copy from private\ntos\rtl\time.c
//
///////////////////////////////////////////////////////////////////////////////
//
// ULONG
// NumberOfLeapYears (
// IN ULONG ElapsedYears
// );
//
// The number of leap years is simply the number of years divided by 4
// minus years divided by 100 plus years divided by 400. This says
// that every four years is a leap year except centuries, and the
// exception to the exception is the quadricenturies
//
#define NumberOfLeapYears(YEARS) ( \
((YEARS) / 4) - ((YEARS) / 100) + ((YEARS) / 400) \
)
//
// ULONG
// ElapsedYearsToDays (
// IN ULONG ElapsedYears
// );
//
// The number of days contained in elapsed years is simply the number
// of years times 365 (because every year has at least 365 days) plus
// the number of leap years there are (i.e., the number of 366 days years)
//
#define ElapsedYearsToDays(YEARS) ( \
((YEARS) * 365) + NumberOfLeapYears(YEARS) \
)
//
// BOOLEAN
// IsLeapYear (
// IN ULONG ElapsedYears
// );
//
// If it is an even 400 or a non century leapyear then the
// answer is true otherwise it's false
//
#define IsLeapYear(YEARS) ( \
(((YEARS) % 400 == 0) || \
((YEARS) % 100 != 0) && ((YEARS) % 4 == 0)) ? \
TRUE \
: \
FALSE \
)
//
// ULONG
// MaxDaysInMonth (
// IN ULONG Year,
// IN ULONG Month
// );
//
// The maximum number of days in a month depend on the year and month.
// It is the difference between the days to the month and the days
// to the following month
//
#define MaxDaysInMonth(YEAR,MONTH) ( \
IsLeapYear(YEAR) ? \
LeapYearDaysPrecedingMonth[(MONTH) + 1] - \
LeapYearDaysPrecedingMonth[(MONTH)] \
: \
NormalYearDaysPrecedingMonth[(MONTH) + 1] - \
NormalYearDaysPrecedingMonth[(MONTH)] \
)
#define ConvertDaysToMilliseconds(DAYS) ( \
Int32x32To64( (DAYS), 86400000 ) \
)
//
// The following two tables map a month index to the number of days preceding
// the month in the year. Both tables are zero based. For example, 1 (Feb)
// has 31 days preceding it. To help calculate the maximum number of days
// in a month each table has 13 entries, so the number of days in a month
// of index i is the table entry of i+1 minus the table entry of i.
//
CONST USHORT LeapYearDaysPrecedingMonth[13] = {
0, // January
31, // February
31+29, // March
31+29+31, // April
31+29+31+30, // May
31+29+31+30+31, // June
31+29+31+30+31+30, // July
31+29+31+30+31+30+31, // August
31+29+31+30+31+30+31+31, // September
31+29+31+30+31+30+31+31+30, // October
31+29+31+30+31+30+31+31+30+31, // November
31+29+31+30+31+30+31+31+30+31+30, // December
31+29+31+30+31+30+31+31+30+31+30+31};
CONST USHORT NormalYearDaysPrecedingMonth[13] = {
0, // January
31, // February
31+28, // March
31+28+31, // April
31+28+31+30, // May
31+28+31+30+31, // June
31+28+31+30+31+30, // July
31+28+31+30+31+30+31, // August
31+28+31+30+31+30+31+31, // September
31+28+31+30+31+30+31+31+30, // October
31+28+31+30+31+30+31+31+30+31, // November
31+28+31+30+31+30+31+31+30+31+30, // December
31+28+31+30+31+30+31+31+30+31+30+31};
//
// These are known constants used to convert 1970 and 1980 times to 1601
// times. They are the number of seconds from the 1601 base to the start
// of 1970 and the start of 1980. The number of seconds from 1601 to
// 1970 is 369 years worth, or (369 * 365) + 89 leap days = 134774 days, or
// 134774 * 864000 seconds, which is equal to the large integer defined
// below. The number of seconds from 1601 to 1980 is 379 years worth, or etc.
//
const LARGE_INTEGER SecondsToStartOf1970 = {0xb6109100, 0x00000002};
const LARGE_INTEGER SecondsToStartOf1980 = {0xc8df3700, 0x00000002};
///////////////////////////////////////////////////////////////////////////////
//
// Above portion copy from private\ntos\rtl\time.c
//
//
///////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
void
ConvertInt64ToFileTime(
const __int64* pint64,
FILETIME* pft
)
/*++
--*/
{
pft->dwLowDateTime = (DWORD)(*pint64 & 0xFFFFFFFF);
pft->dwHighDateTime = (LONG) (*pint64 >> 32);
return;
}
//---------------------------------------------------------------------------
void
ConvertFileTimeToInt64(
const FILETIME* pft,
__int64* pint64
)
/*++
--*/
{
ULARGE_INTEGER ul;
ul.LowPart = pft->dwLowDateTime;
ul.HighPart = pft->dwHighDateTime;
*pint64 = (__int64)ul.QuadPart;
return;
}
//---------------------------------------------------------------------------
void
ConvertInt64ToUlargeInt(
const __int64* pint64,
ULARGE_INTEGER* pularge
)
/*++
--*/
{
pularge->QuadPart = *pint64;
return;
}
//---------------------------------------------------------------------------
BOOL
MyMkTime(
SYSTEMTIME* psysTime,
FILETIME* pft
)
/*++
Similar to standard C runtime mktime() except it operate on
SYSTEMTIME, note, BUG in mktime() that it lost one day, e.g,
add 9 year, 25 months to 1970/1/1, mktime returns 1981/1/31
instead of 1981/2/1
--*/
{
DWORD dwMilliseconds;
ULARGE_INTEGER ul100NsSince1970;
LONGLONG ul100NsSince1601;
LONGLONG ul100Ns;
FILETIME ft;
BOOL bSuccess;
DWORD dwDaysSince1970;
//
// day/hour/mins/second to 100ns
dwMilliseconds = ((psysTime->wHour * 60 + psysTime->wMinute) * 60 + psysTime->wSecond) * 1000 + psysTime->wMilliseconds;
ul100Ns = UInt32x32To64( dwMilliseconds, 10000 );
//
// Convert year/month/day to days since 1980
while( psysTime->wMonth > 12 )
{
// our month is inclusive
psysTime->wYear ++;
psysTime->wMonth -= 12;
}
dwDaysSince1970 = ElapsedYearsToDays(psysTime->wYear) - ElapsedYearsToDays(1970);
// dwDaysSince1970 already included 1/1/1970
dwDaysSince1970 += psysTime->wDay - 1;
if(IsLeapYear(psysTime->wYear) == TRUE)
{
dwDaysSince1970 += LeapYearDaysPrecedingMonth[psysTime->wMonth - 1];
dwDaysSince1970--;
}
else
{
dwDaysSince1970 += NormalYearDaysPrecedingMonth[psysTime->wMonth - 1];
}
//
// Convert days since 1980 to 100 ns since 1980
ul100NsSince1601 = ConvertDaysToMilliseconds(dwDaysSince1970) * 10000 + ul100Ns;
ul100NsSince1601 += (SecondsToStartOf1970.QuadPart * 10000000);
ConvertInt64ToFileTime(&ul100NsSince1601, &ft);
bSuccess = FileTimeToSystemTime( &ft, psysTime );
if(bSuccess == TRUE && pft != NULL)
{
*pft = ft;
}
return bSuccess;
}