269 lines
7.6 KiB
C++
269 lines
7.6 KiB
C++
#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;
|
|
}
|