summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/stdtimep.h
blob: 875faac3f47e109d523f1d1d2ea01a26d85fa18a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
/*++

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 LARGE_INTEGER SecondsToStartOf1970;
extern 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_