1 /*++ 2 3 Copyright (c) 1989-2000 Microsoft Corporation 4 5 Module Name: 6 7 TimeSup.c 8 9 Abstract: 10 11 This module implements the Fat Time conversion support routines 12 13 14 --*/ 15 16 #include "fatprocs.h" 17 18 #ifdef ALLOC_PRAGMA 19 #pragma alloc_text(PAGE, FatNtTimeToFatTime) 20 #pragma alloc_text(PAGE, FatFatDateToNtTime) 21 #pragma alloc_text(PAGE, FatFatTimeToNtTime) 22 #pragma alloc_text(PAGE, FatGetCurrentFatTime) 23 #endif 24 25 _Success_(return != FALSE) 26 BOOLEAN 27 FatNtTimeToFatTime ( 28 _In_ PIRP_CONTEXT IrpContext, 29 _In_ PLARGE_INTEGER NtTime, 30 _In_ BOOLEAN Rounding, 31 _Out_ PFAT_TIME_STAMP FatTime, 32 _Out_opt_ PUCHAR TenMsecs 33 ) 34 35 /*++ 36 37 Routine Description: 38 39 This routine converts an NtTime value to its corresponding Fat time value. 40 41 Arguments: 42 43 NtTime - Supplies the Nt GMT Time value to convert from 44 45 Rounding - Indicates whether the NT time should be rounded up to a FAT boundary. 46 This should only be done *once* in the lifetime of a timestamp (important 47 for tunneling, which will cause a timestamp to pass through at least twice). 48 If true, rounded up. If false, rounded down to 10ms boundary. This obeys 49 the rules for non-creation time and creation times (respectively). 50 51 FatTime - Receives the equivalent Fat time value 52 53 TenMsecs - Optionally receive the number of tens of milliseconds the NtTime, after 54 any rounding, is greater than the FatTime 55 56 Return Value: 57 58 BOOLEAN - TRUE if the Nt time value is within the range of Fat's 59 time range, and FALSE otherwise 60 61 --*/ 62 63 { 64 TIME_FIELDS TimeFields; 65 66 PAGED_CODE(); 67 68 // 69 // Convert the input to the a time field record. 70 // 71 72 if (Rounding) { 73 74 // 75 // Add almost two seconds to round up to the nearest double second. 76 // 77 78 NtTime->QuadPart = NtTime->QuadPart + AlmostTwoSeconds; 79 } 80 81 ExSystemTimeToLocalTime( NtTime, NtTime ); 82 83 RtlTimeToTimeFields( NtTime, &TimeFields ); 84 85 // 86 // Check the range of the date found in the time field record 87 // 88 89 if ((TimeFields.Year < 1980) || (TimeFields.Year > (1980 + 127))) { 90 91 ExLocalTimeToSystemTime( NtTime, NtTime ); 92 93 return FALSE; 94 } 95 96 // 97 // The year will fit in Fat so simply copy over the information 98 // 99 100 FatTime->Time.DoubleSeconds = (USHORT)(TimeFields.Second / 2); 101 FatTime->Time.Minute = (USHORT)(TimeFields.Minute); 102 FatTime->Time.Hour = (USHORT)(TimeFields.Hour); 103 104 FatTime->Date.Year = (USHORT)(TimeFields.Year - 1980); 105 FatTime->Date.Month = (USHORT)(TimeFields.Month); 106 FatTime->Date.Day = (USHORT)(TimeFields.Day); 107 108 if (TenMsecs) { 109 110 if (!Rounding) { 111 112 // 113 // If the number of seconds was not divisible by two, then there 114 // is another second of time (1 sec, 3 sec, etc.) Note we round down 115 // the number of milleconds onto tens of milleseconds boundaries. 116 // 117 118 #ifdef _MSC_VER 119 #pragma warning( push ) 120 #pragma warning( disable: 4244 ) 121 #endif 122 *TenMsecs = (TimeFields.Milliseconds / 10) + 123 ((TimeFields.Second % 2) * 100); 124 #ifdef _MSC_VER 125 #pragma warning( pop ) 126 #endif 127 } else { 128 129 // 130 // If we rounded up, we have in effect changed the NT time. Therefore, 131 // it does not differ from the FAT time. 132 // 133 134 *TenMsecs = 0; 135 } 136 } 137 138 if (Rounding) { 139 140 // 141 // Slice off non-FAT boundary time and convert back to 64bit form 142 // 143 144 TimeFields.Milliseconds = 0; 145 TimeFields.Second -= TimeFields.Second % 2; 146 147 } else { 148 149 // 150 // Round down to 10ms boundary 151 // 152 153 TimeFields.Milliseconds -= TimeFields.Milliseconds % 10; 154 } 155 156 // 157 // Convert back to NT time 158 // 159 160 (VOID) RtlTimeFieldsToTime(&TimeFields, NtTime); 161 162 ExLocalTimeToSystemTime( NtTime, NtTime ); 163 164 UNREFERENCED_PARAMETER( IrpContext ); 165 166 return TRUE; 167 } 168 169 170 LARGE_INTEGER 171 FatFatDateToNtTime ( 172 _In_ PIRP_CONTEXT IrpContext, 173 _In_ FAT_DATE FatDate 174 ) 175 176 /*++ 177 178 Routine Description: 179 180 This routine converts a Fat datev value to its corresponding Nt GMT 181 Time value. 182 183 Arguments: 184 185 FatDate - Supplies the Fat Date to convert from 186 187 Return Value: 188 189 LARGE_INTEGER - Receives the corresponding Nt Time value 190 191 --*/ 192 193 { 194 TIME_FIELDS TimeFields; 195 LARGE_INTEGER Time; 196 197 PAGED_CODE(); 198 199 // 200 // Pack the input time/date into a time field record 201 // 202 203 TimeFields.Year = (USHORT)(FatDate.Year + 1980); 204 TimeFields.Month = (USHORT)(FatDate.Month); 205 TimeFields.Day = (USHORT)(FatDate.Day); 206 TimeFields.Hour = (USHORT)0; 207 TimeFields.Minute = (USHORT)0; 208 TimeFields.Second = (USHORT)0; 209 TimeFields.Milliseconds = (USHORT)0; 210 211 // 212 // Convert the time field record to Nt LARGE_INTEGER, and set it to zero 213 // if we were given a bogus time. 214 // 215 216 if (!RtlTimeFieldsToTime( &TimeFields, &Time )) { 217 218 Time.LowPart = 0; 219 Time.HighPart = 0; 220 221 } else { 222 223 ExLocalTimeToSystemTime( &Time, &Time ); 224 } 225 226 return Time; 227 228 UNREFERENCED_PARAMETER( IrpContext ); 229 } 230 231 232 LARGE_INTEGER 233 FatFatTimeToNtTime ( 234 _In_ PIRP_CONTEXT IrpContext, 235 _In_ FAT_TIME_STAMP FatTime, 236 _In_ UCHAR TenMilliSeconds 237 ) 238 239 /*++ 240 241 Routine Description: 242 243 This routine converts a Fat time value pair to its corresponding Nt GMT 244 Time value. 245 246 Arguments: 247 248 FatTime - Supplies the Fat Time to convert from 249 250 TenMilliSeconds - A 10 Milisecond resolution 251 252 Return Value: 253 254 LARGE_INTEGER - Receives the corresponding Nt GMT Time value 255 256 --*/ 257 258 { 259 TIME_FIELDS TimeFields; 260 LARGE_INTEGER Time; 261 262 PAGED_CODE(); 263 264 // 265 // Pack the input time/date into a time field record 266 // 267 268 TimeFields.Year = (USHORT)(FatTime.Date.Year + 1980); 269 TimeFields.Month = (USHORT)(FatTime.Date.Month); 270 TimeFields.Day = (USHORT)(FatTime.Date.Day); 271 TimeFields.Hour = (USHORT)(FatTime.Time.Hour); 272 TimeFields.Minute = (USHORT)(FatTime.Time.Minute); 273 TimeFields.Second = (USHORT)(FatTime.Time.DoubleSeconds * 2); 274 275 if (TenMilliSeconds != 0) { 276 277 TimeFields.Second += (USHORT)(TenMilliSeconds / 100); 278 TimeFields.Milliseconds = (USHORT)((TenMilliSeconds % 100) * 10); 279 280 } else { 281 282 TimeFields.Milliseconds = (USHORT)0; 283 } 284 285 // 286 // If the second value is greater than 59 then we truncate it to 0. 287 // Note that this can't happen with a proper FAT timestamp. 288 // 289 290 if (TimeFields.Second > 59) { 291 292 TimeFields.Second = 0; 293 } 294 295 // 296 // Convert the time field record to Nt LARGE_INTEGER, and set it to zero 297 // if we were given a bogus time. 298 // 299 300 if (!RtlTimeFieldsToTime( &TimeFields, &Time )) { 301 302 Time.LowPart = 0; 303 Time.HighPart = 0; 304 305 } else { 306 307 ExLocalTimeToSystemTime( &Time, &Time ); 308 } 309 310 return Time; 311 312 UNREFERENCED_PARAMETER( IrpContext ); 313 } 314 315 316 FAT_TIME_STAMP 317 FatGetCurrentFatTime ( 318 _In_ PIRP_CONTEXT IrpContext 319 ) 320 321 /*++ 322 323 Routine Description: 324 325 This routine returns the current system time in Fat time 326 327 Arguments: 328 329 Return Value: 330 331 FAT_TIME_STAMP - Receives the current system time 332 333 --*/ 334 335 { 336 LARGE_INTEGER Time; 337 TIME_FIELDS TimeFields; 338 FAT_TIME_STAMP FatTime; 339 340 PAGED_CODE(); 341 342 // 343 // Get the current system time, and map it into a time field record. 344 // 345 346 KeQuerySystemTime( &Time ); 347 348 ExSystemTimeToLocalTime( &Time, &Time ); 349 350 // 351 // Always add almost two seconds to round up to the nearest double second. 352 // 353 354 Time.QuadPart = Time.QuadPart + AlmostTwoSeconds; 355 356 (VOID)RtlTimeToTimeFields( &Time, &TimeFields ); 357 358 // 359 // Now simply copy over the information 360 // 361 362 FatTime.Time.DoubleSeconds = (USHORT)(TimeFields.Second / 2); 363 FatTime.Time.Minute = (USHORT)(TimeFields.Minute); 364 FatTime.Time.Hour = (USHORT)(TimeFields.Hour); 365 366 FatTime.Date.Year = (USHORT)(TimeFields.Year - 1980); 367 FatTime.Date.Month = (USHORT)(TimeFields.Month); 368 FatTime.Date.Day = (USHORT)(TimeFields.Day); 369 370 UNREFERENCED_PARAMETER( IrpContext ); 371 372 return FatTime; 373 } 374 375 376