summaryrefslogtreecommitdiff
path: root/filesys/fastfat/timesup.c
blob: 659c9514c14278e6ea849fc5e1cb9153b8094b4a (plain)
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
/*++

Copyright (c) 1989-2000 Microsoft Corporation

Module Name:

    TimeSup.c

Abstract:

    This module implements the Fat Time conversion support routines


--*/

#include "FatProcs.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatNtTimeToFatTime)
#pragma alloc_text(PAGE, FatFatDateToNtTime)
#pragma alloc_text(PAGE, FatFatTimeToNtTime)
#pragma alloc_text(PAGE, FatGetCurrentFatTime)
#endif

_Success_(return != FALSE)
BOOLEAN
FatNtTimeToFatTime (
    _In_ PIRP_CONTEXT IrpContext,
    _In_ PLARGE_INTEGER NtTime,
    _In_ BOOLEAN Rounding,
    _Out_ PFAT_TIME_STAMP FatTime,
    _Out_opt_ PUCHAR TenMsecs
    )

/*++

Routine Description:

    This routine converts an NtTime value to its corresponding Fat time value.

Arguments:

    NtTime - Supplies the Nt GMT Time value to convert from

    Rounding - Indicates whether the NT time should be rounded up to a FAT boundary.
        This should only be done *once* in the lifetime of a timestamp (important
        for tunneling, which will cause a timestamp to pass through at least twice).
        If true, rounded up. If false, rounded down to 10ms boundary. This obeys
        the rules for non-creation time and creation times (respectively).

    FatTime - Receives the equivalent Fat time value

    TenMsecs - Optionally receive the number of tens of milliseconds the NtTime, after
        any rounding, is greater than the FatTime

Return Value:

    BOOLEAN - TRUE if the Nt time value is within the range of Fat's
        time range, and FALSE otherwise

--*/

{
    TIME_FIELDS TimeFields;

    PAGED_CODE();

    //
    //  Convert the input to the a time field record.
    //

    if (Rounding) {

        //
        //   Add almost two seconds to round up to the nearest double second.
        //
    
        NtTime->QuadPart = NtTime->QuadPart + AlmostTwoSeconds;
    }

    ExSystemTimeToLocalTime( NtTime, NtTime );

    RtlTimeToTimeFields( NtTime, &TimeFields );

    //
    //  Check the range of the date found in the time field record
    //

    if ((TimeFields.Year < 1980) || (TimeFields.Year > (1980 + 127))) {

        ExLocalTimeToSystemTime( NtTime, NtTime );

        return FALSE;
    }

    //
    //  The year will fit in Fat so simply copy over the information
    //

    FatTime->Time.DoubleSeconds = (USHORT)(TimeFields.Second / 2);
    FatTime->Time.Minute        = (USHORT)(TimeFields.Minute);
    FatTime->Time.Hour          = (USHORT)(TimeFields.Hour);

    FatTime->Date.Year          = (USHORT)(TimeFields.Year - 1980);
    FatTime->Date.Month         = (USHORT)(TimeFields.Month);
    FatTime->Date.Day           = (USHORT)(TimeFields.Day);

    if (TenMsecs) {

        if (!Rounding) {

            //
            //  If the number of seconds was not divisible by two, then there
            //  is another second of time (1 sec, 3 sec, etc.) Note we round down
            //  the number of milleconds onto tens of milleseconds boundaries.
            //

#pragma warning( push )
#pragma warning( disable: 4244 )
            *TenMsecs = (TimeFields.Milliseconds / 10) +
                ((TimeFields.Second % 2) * 100);
#pragma warning( pop )
        } else {

            //
            //  If we rounded up, we have in effect changed the NT time. Therefore,
            //  it does not differ from the FAT time.
            //

            *TenMsecs = 0;
        }
    }

    if (Rounding) {

        //
        //  Slice off non-FAT boundary time and convert back to 64bit form
        //

        TimeFields.Milliseconds = 0;
        TimeFields.Second -= TimeFields.Second % 2;

    } else {

        //
        //  Round down to 10ms boundary
        //

        TimeFields.Milliseconds -= TimeFields.Milliseconds % 10;
    }

    //
    //  Convert back to NT time
    //

    (VOID) RtlTimeFieldsToTime(&TimeFields, NtTime);

    ExLocalTimeToSystemTime( NtTime, NtTime );

    UNREFERENCED_PARAMETER( IrpContext );

    return TRUE;
}


LARGE_INTEGER
FatFatDateToNtTime (
    _In_ PIRP_CONTEXT IrpContext,
    _In_ FAT_DATE FatDate
    )

/*++

Routine Description:

    This routine converts a Fat datev value to its corresponding Nt GMT
    Time value.

Arguments:

    FatDate - Supplies the Fat Date to convert from

Return Value:

    LARGE_INTEGER - Receives the corresponding Nt Time value

--*/

{
    TIME_FIELDS TimeFields;
    LARGE_INTEGER Time;

    PAGED_CODE();

    //
    //  Pack the input time/date into a time field record
    //

    TimeFields.Year         = (USHORT)(FatDate.Year + 1980);
    TimeFields.Month        = (USHORT)(FatDate.Month);
    TimeFields.Day          = (USHORT)(FatDate.Day);
    TimeFields.Hour         = (USHORT)0;
    TimeFields.Minute       = (USHORT)0;
    TimeFields.Second       = (USHORT)0;
    TimeFields.Milliseconds = (USHORT)0;

    //
    //  Convert the time field record to Nt LARGE_INTEGER, and set it to zero
    //  if we were given a bogus time.
    //

    if (!RtlTimeFieldsToTime( &TimeFields, &Time )) {

        Time.LowPart = 0;
        Time.HighPart = 0;

    } else {

        ExLocalTimeToSystemTime( &Time, &Time );
    }

    return Time;

    UNREFERENCED_PARAMETER( IrpContext );
}


LARGE_INTEGER
FatFatTimeToNtTime (
    _In_ PIRP_CONTEXT IrpContext,
    _In_ FAT_TIME_STAMP FatTime,
    _In_ UCHAR TenMilliSeconds
    )

/*++

Routine Description:

    This routine converts a Fat time value pair to its corresponding Nt GMT
    Time value.

Arguments:

    FatTime - Supplies the Fat Time to convert from

    TenMilliSeconds - A 10 Milisecond resolution

Return Value:

    LARGE_INTEGER - Receives the corresponding Nt GMT Time value

--*/

{
    TIME_FIELDS TimeFields;
    LARGE_INTEGER Time;

    PAGED_CODE();

    //
    //  Pack the input time/date into a time field record
    //

    TimeFields.Year         = (USHORT)(FatTime.Date.Year + 1980);
    TimeFields.Month        = (USHORT)(FatTime.Date.Month);
    TimeFields.Day          = (USHORT)(FatTime.Date.Day);
    TimeFields.Hour         = (USHORT)(FatTime.Time.Hour);
    TimeFields.Minute       = (USHORT)(FatTime.Time.Minute);
    TimeFields.Second       = (USHORT)(FatTime.Time.DoubleSeconds * 2);

    if (TenMilliSeconds != 0) {

        TimeFields.Second      += (USHORT)(TenMilliSeconds / 100);
        TimeFields.Milliseconds = (USHORT)((TenMilliSeconds % 100) * 10);

    } else {

        TimeFields.Milliseconds = (USHORT)0;
    }

    //
    //  If the second value is greater than 59 then we truncate it to 0.
    //  Note that this can't happen with a proper FAT timestamp.
    //

    if (TimeFields.Second > 59) {

        TimeFields.Second = 0;
    }

    //
    //  Convert the time field record to Nt LARGE_INTEGER, and set it to zero
    //  if we were given a bogus time.
    //

    if (!RtlTimeFieldsToTime( &TimeFields, &Time )) {

        Time.LowPart = 0;
        Time.HighPart = 0;

    } else {

        ExLocalTimeToSystemTime( &Time, &Time );
    }

    return Time;

    UNREFERENCED_PARAMETER( IrpContext );
}


FAT_TIME_STAMP
FatGetCurrentFatTime (
    _In_ PIRP_CONTEXT IrpContext
    )

/*++

Routine Description:

    This routine returns the current system time in Fat time

Arguments:

Return Value:

    FAT_TIME_STAMP - Receives the current system time

--*/

{
    LARGE_INTEGER Time;
    TIME_FIELDS TimeFields;
    FAT_TIME_STAMP FatTime;

    PAGED_CODE();

    //
    //  Get the current system time, and map it into a time field record.
    //

    KeQuerySystemTime( &Time );

    ExSystemTimeToLocalTime( &Time, &Time );

    //
    //  Always add almost two seconds to round up to the nearest double second.
    //

    Time.QuadPart = Time.QuadPart + AlmostTwoSeconds;

    (VOID)RtlTimeToTimeFields( &Time, &TimeFields );

    //
    //  Now simply copy over the information
    //

    FatTime.Time.DoubleSeconds = (USHORT)(TimeFields.Second / 2);
    FatTime.Time.Minute        = (USHORT)(TimeFields.Minute);
    FatTime.Time.Hour          = (USHORT)(TimeFields.Hour);

    FatTime.Date.Year          = (USHORT)(TimeFields.Year - 1980);
    FatTime.Date.Month         = (USHORT)(TimeFields.Month);
    FatTime.Date.Day           = (USHORT)(TimeFields.Day);

    UNREFERENCED_PARAMETER( IrpContext );

    return FatTime;
}