mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
450 lines
12 KiB
450 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
stdtimep.h
|
|
|
|
Abstract:
|
|
|
|
This module contains definitions and function prototypes which are local to
|
|
stdime.c and fmttime.c.
|
|
|
|
Author:
|
|
|
|
Rob McKaughan (t-robmc) 17-Jul-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _STD_TIME_P_
|
|
#define _STD_TIME_P_
|
|
|
|
//
|
|
// These are the magic numbers needed to do our extended division. The
|
|
// only numbers we ever need to divide by are
|
|
//
|
|
// 10,000 = convert 100ns tics to millisecond tics
|
|
//
|
|
// 10,000,000 = convert 100ns tics to one second tics
|
|
//
|
|
// 86,400,000 = convert Millisecond tics to one day tics
|
|
//
|
|
|
|
extern LARGE_INTEGER Magic10000;
|
|
#define SHIFT10000 13
|
|
|
|
extern LARGE_INTEGER Magic10000000;
|
|
#define SHIFT10000000 23
|
|
|
|
extern LARGE_INTEGER Magic86400000;
|
|
#define SHIFT86400000 26
|
|
|
|
//
|
|
// To make the code more readable we'll also define some macros to
|
|
// do the actual division for use
|
|
//
|
|
|
|
#define Convert100nsToMilliseconds(LARGE_INTEGER) ( \
|
|
RtlExtendedMagicDivide( (LARGE_INTEGER), Magic10000, SHIFT10000 ) \
|
|
)
|
|
|
|
#define ConvertMillisecondsTo100ns(MILLISECONDS) ( \
|
|
RtlExtendedIntegerMultiply( (MILLISECONDS), 10000 ) \
|
|
)
|
|
|
|
#define Convert100nsToSeconds(LARGE_INTEGER) ( \
|
|
RtlExtendedMagicDivide( (LARGE_INTEGER), Magic10000000, SHIFT10000000 ) \
|
|
)
|
|
|
|
#define ConvertSecondsTo100ns(SECONDS) ( \
|
|
RtlExtendedIntegerMultiply( (SECONDS), 10000000L ) \
|
|
)
|
|
|
|
#define ConvertMillisecondsToDays(LARGE_INTEGER) ( \
|
|
RtlExtendedMagicDivide( (LARGE_INTEGER), Magic86400000, SHIFT86400000 ) \
|
|
)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Macros for Time Differentials and Time Revisions //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// The following define the minimum and maximum possible values for the Time
|
|
// Differential Factor as defined by ISO 4031-1978.
|
|
//
|
|
|
|
#define MAX_STDTIME_TDF (780)
|
|
#define MIN_STDTIME_TDF (-720)
|
|
|
|
//
|
|
// The revision of this design (will be inserted in the revision field of any
|
|
// STANDARD_TIMEs created by this revision).
|
|
//
|
|
|
|
#define STDTIME_REVISION (4)
|
|
|
|
|
|
//
|
|
// The number of bits we need to shift to get to and from a revision in a
|
|
// StdTime.TdfAndRevision field.
|
|
//
|
|
|
|
#define STDTIME_REVISION_SHIFT 12
|
|
|
|
|
|
//
|
|
// USHORT
|
|
// ShiftStandardTimeRevision(
|
|
// IN USHORT Rev
|
|
// )
|
|
// Description:
|
|
// This routine shifts the given revision number to its proper place for
|
|
// storing in a STANDARD_TIME.TdfAndRevision field.
|
|
//
|
|
|
|
#define ShiftStandardTimeRevision(Rev) \
|
|
((USHORT) ((Rev) << STDTIME_REVISION_SHIFT))
|
|
|
|
|
|
//
|
|
// The pre-shifted value of the current revision
|
|
//
|
|
|
|
#define SHIFTED_STDTIME_REVISION (ShiftStandardTimeRevision(STDTIME_REVISION))
|
|
|
|
|
|
//
|
|
// The bit mask used to mask a STANDARD_TIME.TdfAndRevision field to retrieve
|
|
// the Tdf value.
|
|
//
|
|
|
|
#define TDF_MASK ((USHORT) 0x0fff)
|
|
|
|
|
|
//
|
|
// USHORT
|
|
// MaskStandardTimeTdf(
|
|
// IN USHORT Tdf
|
|
// )
|
|
// Description:
|
|
// This routine masks the given tdf field with TDF_MASK and returns the
|
|
// result.
|
|
//
|
|
// BUG: Byte order dependant
|
|
//
|
|
|
|
#define MaskStandardTimeTdf(Tdf) ((USHORT) ((Tdf) & TDF_MASK))
|
|
|
|
|
|
//
|
|
// SHORT
|
|
// GetStandardTimeTdf(
|
|
// IN STANDARD_TIME
|
|
// )
|
|
// Description:
|
|
// This routine gets the Time Differential Factor from a tdf field and
|
|
// makes any adjustments necessary to preserve the sign of the TDF.
|
|
// The resulting TDF is returned.
|
|
//
|
|
// Since the TDF is stored as a signed 12 bit int, it's sign bit is the
|
|
// bit 0x0800. To make it a 16 bit negative, we subtract 0x1000 from the
|
|
// bottome 12 bits of the TdfAndRevision field.
|
|
//
|
|
// BUG: Byte order dependant
|
|
//
|
|
|
|
#define GetStandardTimeTdf(StdTime) \
|
|
((SHORT) \
|
|
(((StdTime)->TdfAndRevision) & 0x0800) \
|
|
? (MaskStandardTimeTdf((StdTime)->TdfAndRevision) - 0x1000) \
|
|
: MaskStandardTimeTdf((StdTime)->TdfAndRevision) \
|
|
)
|
|
|
|
|
|
//
|
|
// USHORT
|
|
// GetStandardTimeRev(
|
|
// IN USHORT Tdf
|
|
// )
|
|
// Description:
|
|
// This routine gets the revision number from a tdf field and returns it
|
|
// shifted back down to its place as a SHORT.
|
|
//
|
|
|
|
#define GetStandardTimeRev(StdTime) \
|
|
((USHORT) (((StdTime)->TdfAndRevision) >> STDTIME_REVISION_SHIFT))
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Tests for absolute and delta times //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// BOOLEAN
|
|
// IsPositive(
|
|
// IN LARGE_INTEGER Time
|
|
// )
|
|
// Returns:
|
|
// TRUE - if the time in Time is positive.
|
|
// FALSE - if Time is negative.
|
|
//
|
|
|
|
#define IsPositive(Time) \
|
|
( ((Time).HighPart > 0) || (((Time).HighPart = 0) & ((Time).LowPart > 0)) )
|
|
|
|
//
|
|
// BOOLEAN
|
|
// IsAbsoluteTime(
|
|
// IN PSTANDARDTIME Time
|
|
// )
|
|
// Returns:
|
|
// TRUE - if the given time is an absolute time
|
|
// FALSE - If the given time is not an absolute time
|
|
//
|
|
|
|
#define IsAbsoluteTime(Time) \
|
|
( IsPositive(Time->SimpleTime) )
|
|
|
|
|
|
//
|
|
// BOOLEAN
|
|
// IsDeltaTime(
|
|
// IN PSTANDARDTIME Time
|
|
// )
|
|
// Returns:
|
|
// TRUE - if the given time is a delta time
|
|
// FALSE - If the given time is not a delta time
|
|
//
|
|
|
|
#define IsDeltaTime(Time) \
|
|
( !IsAbsoluteTime(Time) )
|
|
|
|
|
|
//
|
|
// BOOLEAN
|
|
// GreaterThanTime(
|
|
// IN PLARGE_INTEGER Time1,
|
|
// IN PLARGE_INTEGER Time2
|
|
// )
|
|
// Returns:
|
|
// TRUE - If Time1 is greater (older) than Time2
|
|
// FALSE - If not
|
|
//
|
|
// BUG: Byte order dependant
|
|
// BUG: Only works on absolute times
|
|
//
|
|
|
|
#define GreaterThanTime(Time1, Time2) \
|
|
( \
|
|
((Time1).HighPart > (Time2).HighPart) \
|
|
|| \
|
|
( \
|
|
((Time1).HighPart == (Time2).HighPart) \
|
|
&& \
|
|
((Time1).LowPart > (Time2).LowPart) \
|
|
) \
|
|
)
|
|
|
|
|
|
//
|
|
// BOOLEAN
|
|
// GreaterThanStandardTime(
|
|
// IN PSTANDARD_TIME Time1,
|
|
// IN PSTANDARD_TIME Time2
|
|
// )
|
|
// Returns:
|
|
// TRUE - If Time1 is greater (older) than Time2
|
|
// FALSE - If not
|
|
//
|
|
|
|
#define GreaterThanStdTime(Time1, Time2) \
|
|
GreaterThanTime((Time1).SimpleTime, (Time2).SimpleTime)
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// The following definitions and declarations are some important constants /
|
|
// used in the time conversion routines /
|
|
// /
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// This is the week day that January 1st, 1601 fell on (a Monday)
|
|
//
|
|
|
|
#define WEEKDAY_OF_1601 1
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
// These are declared in time.c
|
|
//
|
|
|
|
extern const LARGE_INTEGER SecondsToStartOf1970;
|
|
extern const LARGE_INTEGER SecondsToStartOf1980;
|
|
|
|
|
|
//
|
|
// ULONG
|
|
// ElapsedDaysToYears (
|
|
// IN ULONG ElapsedDays
|
|
// );
|
|
//
|
|
// To be completely true to the Gregorian calendar the equation to
|
|
// go from days to years is really
|
|
//
|
|
// ElapsedDays / 365.2425
|
|
//
|
|
// But because we are doing the computation in ulong integer arithmetic
|
|
// and the LARGE_INTEGER variable limits the number of expressible days to around
|
|
// 11,000,000 we use the following computation
|
|
//
|
|
// (ElapsedDays * 128 + 127) / (365.2425 * 128)
|
|
//
|
|
// which will be off from the Gregorian calendar in about 150,000 years
|
|
// but that doesn't really matter because LARGE_INTEGER can only express around
|
|
// 30,000 years
|
|
//
|
|
|
|
#define ElapsedDaysToYears(DAYS) ( \
|
|
((DAYS) * 128 + 127) / 46751 \
|
|
)
|
|
|
|
//
|
|
// 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)] \
|
|
)
|
|
|
|
|
|
//
|
|
// Local utlity function prototypes
|
|
//
|
|
|
|
VOID
|
|
RtlpConvert48To64(
|
|
IN PSTDTIME_ERROR num48,
|
|
OUT LARGE_INTEGER *num64
|
|
);
|
|
|
|
NTSTATUS
|
|
RtlpConvert64To48(
|
|
IN LARGE_INTEGER num64,
|
|
OUT PSTDTIME_ERROR num48
|
|
);
|
|
|
|
LARGE_INTEGER
|
|
RtlpTimeToLargeInt(
|
|
IN LARGE_INTEGER Time
|
|
);
|
|
|
|
LARGE_INTEGER
|
|
RtlpLargeIntToTime(
|
|
IN LARGE_INTEGER Int
|
|
);
|
|
|
|
NTSTATUS
|
|
RtlpAdd48Int(
|
|
IN PSTDTIME_ERROR First48,
|
|
IN PSTDTIME_ERROR Second48,
|
|
IN PSTDTIME_ERROR Result48
|
|
);
|
|
|
|
NTSTATUS
|
|
RtlpAddTime(
|
|
IN LARGE_INTEGER Time1,
|
|
IN LARGE_INTEGER Time2,
|
|
OUT PLARGE_INTEGER Result
|
|
);
|
|
|
|
NTSTATUS
|
|
RtlpSubtractTime(
|
|
IN LARGE_INTEGER Time1,
|
|
IN LARGE_INTEGER Time2,
|
|
OUT PLARGE_INTEGER Result
|
|
);
|
|
|
|
LARGE_INTEGER
|
|
RtlpAbsTime(
|
|
IN LARGE_INTEGER Time
|
|
);
|
|
|
|
#endif //_STD_TIME_P_
|