Source code of Windows XP (NT5)
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.

268 lines
7.6 KiB

  1. #include "stdafx.h"
  2. #include <windows.h>
  3. #include "helper.h"
  4. ///////////////////////////////////////////////////////////////////////////////
  5. //
  6. // Portion copy from private\ntos\rtl\time.c
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. //
  10. // ULONG
  11. // NumberOfLeapYears (
  12. // IN ULONG ElapsedYears
  13. // );
  14. //
  15. // The number of leap years is simply the number of years divided by 4
  16. // minus years divided by 100 plus years divided by 400. This says
  17. // that every four years is a leap year except centuries, and the
  18. // exception to the exception is the quadricenturies
  19. //
  20. #define NumberOfLeapYears(YEARS) ( \
  21. ((YEARS) / 4) - ((YEARS) / 100) + ((YEARS) / 400) \
  22. )
  23. //
  24. // ULONG
  25. // ElapsedYearsToDays (
  26. // IN ULONG ElapsedYears
  27. // );
  28. //
  29. // The number of days contained in elapsed years is simply the number
  30. // of years times 365 (because every year has at least 365 days) plus
  31. // the number of leap years there are (i.e., the number of 366 days years)
  32. //
  33. #define ElapsedYearsToDays(YEARS) ( \
  34. ((YEARS) * 365) + NumberOfLeapYears(YEARS) \
  35. )
  36. //
  37. // BOOLEAN
  38. // IsLeapYear (
  39. // IN ULONG ElapsedYears
  40. // );
  41. //
  42. // If it is an even 400 or a non century leapyear then the
  43. // answer is true otherwise it's false
  44. //
  45. #define IsLeapYear(YEARS) ( \
  46. (((YEARS) % 400 == 0) || \
  47. ((YEARS) % 100 != 0) && ((YEARS) % 4 == 0)) ? \
  48. TRUE \
  49. : \
  50. FALSE \
  51. )
  52. //
  53. // ULONG
  54. // MaxDaysInMonth (
  55. // IN ULONG Year,
  56. // IN ULONG Month
  57. // );
  58. //
  59. // The maximum number of days in a month depend on the year and month.
  60. // It is the difference between the days to the month and the days
  61. // to the following month
  62. //
  63. #define MaxDaysInMonth(YEAR,MONTH) ( \
  64. IsLeapYear(YEAR) ? \
  65. LeapYearDaysPrecedingMonth[(MONTH) + 1] - \
  66. LeapYearDaysPrecedingMonth[(MONTH)] \
  67. : \
  68. NormalYearDaysPrecedingMonth[(MONTH) + 1] - \
  69. NormalYearDaysPrecedingMonth[(MONTH)] \
  70. )
  71. #define ConvertDaysToMilliseconds(DAYS) ( \
  72. Int32x32To64( (DAYS), 86400000 ) \
  73. )
  74. //
  75. // The following two tables map a month index to the number of days preceding
  76. // the month in the year. Both tables are zero based. For example, 1 (Feb)
  77. // has 31 days preceding it. To help calculate the maximum number of days
  78. // in a month each table has 13 entries, so the number of days in a month
  79. // of index i is the table entry of i+1 minus the table entry of i.
  80. //
  81. CONST USHORT LeapYearDaysPrecedingMonth[13] = {
  82. 0, // January
  83. 31, // February
  84. 31+29, // March
  85. 31+29+31, // April
  86. 31+29+31+30, // May
  87. 31+29+31+30+31, // June
  88. 31+29+31+30+31+30, // July
  89. 31+29+31+30+31+30+31, // August
  90. 31+29+31+30+31+30+31+31, // September
  91. 31+29+31+30+31+30+31+31+30, // October
  92. 31+29+31+30+31+30+31+31+30+31, // November
  93. 31+29+31+30+31+30+31+31+30+31+30, // December
  94. 31+29+31+30+31+30+31+31+30+31+30+31};
  95. CONST USHORT NormalYearDaysPrecedingMonth[13] = {
  96. 0, // January
  97. 31, // February
  98. 31+28, // March
  99. 31+28+31, // April
  100. 31+28+31+30, // May
  101. 31+28+31+30+31, // June
  102. 31+28+31+30+31+30, // July
  103. 31+28+31+30+31+30+31, // August
  104. 31+28+31+30+31+30+31+31, // September
  105. 31+28+31+30+31+30+31+31+30, // October
  106. 31+28+31+30+31+30+31+31+30+31, // November
  107. 31+28+31+30+31+30+31+31+30+31+30, // December
  108. 31+28+31+30+31+30+31+31+30+31+30+31};
  109. //
  110. // These are known constants used to convert 1970 and 1980 times to 1601
  111. // times. They are the number of seconds from the 1601 base to the start
  112. // of 1970 and the start of 1980. The number of seconds from 1601 to
  113. // 1970 is 369 years worth, or (369 * 365) + 89 leap days = 134774 days, or
  114. // 134774 * 864000 seconds, which is equal to the large integer defined
  115. // below. The number of seconds from 1601 to 1980 is 379 years worth, or etc.
  116. //
  117. const LARGE_INTEGER SecondsToStartOf1970 = {0xb6109100, 0x00000002};
  118. const LARGE_INTEGER SecondsToStartOf1980 = {0xc8df3700, 0x00000002};
  119. ///////////////////////////////////////////////////////////////////////////////
  120. //
  121. // Above portion copy from private\ntos\rtl\time.c
  122. //
  123. //
  124. ///////////////////////////////////////////////////////////////////////////////
  125. //---------------------------------------------------------------------------
  126. void
  127. ConvertInt64ToFileTime(
  128. const __int64* pint64,
  129. FILETIME* pft
  130. )
  131. /*++
  132. --*/
  133. {
  134. pft->dwLowDateTime = (DWORD)(*pint64 & 0xFFFFFFFF);
  135. pft->dwHighDateTime = (LONG) (*pint64 >> 32);
  136. return;
  137. }
  138. //---------------------------------------------------------------------------
  139. void
  140. ConvertFileTimeToInt64(
  141. const FILETIME* pft,
  142. __int64* pint64
  143. )
  144. /*++
  145. --*/
  146. {
  147. ULARGE_INTEGER ul;
  148. ul.LowPart = pft->dwLowDateTime;
  149. ul.HighPart = pft->dwHighDateTime;
  150. *pint64 = (__int64)ul.QuadPart;
  151. return;
  152. }
  153. //---------------------------------------------------------------------------
  154. void
  155. ConvertInt64ToUlargeInt(
  156. const __int64* pint64,
  157. ULARGE_INTEGER* pularge
  158. )
  159. /*++
  160. --*/
  161. {
  162. pularge->QuadPart = *pint64;
  163. return;
  164. }
  165. //---------------------------------------------------------------------------
  166. BOOL
  167. MyMkTime(
  168. SYSTEMTIME* psysTime,
  169. FILETIME* pft
  170. )
  171. /*++
  172. Similar to standard C runtime mktime() except it operate on
  173. SYSTEMTIME, note, BUG in mktime() that it lost one day, e.g,
  174. add 9 year, 25 months to 1970/1/1, mktime returns 1981/1/31
  175. instead of 1981/2/1
  176. --*/
  177. {
  178. DWORD dwMilliseconds;
  179. ULARGE_INTEGER ul100NsSince1970;
  180. LONGLONG ul100NsSince1601;
  181. LONGLONG ul100Ns;
  182. FILETIME ft;
  183. BOOL bSuccess;
  184. DWORD dwDaysSince1970;
  185. //
  186. // day/hour/mins/second to 100ns
  187. dwMilliseconds = ((psysTime->wHour * 60 + psysTime->wMinute) * 60 + psysTime->wSecond) * 1000 + psysTime->wMilliseconds;
  188. ul100Ns = UInt32x32To64( dwMilliseconds, 10000 );
  189. //
  190. // Convert year/month/day to days since 1980
  191. while( psysTime->wMonth > 12 )
  192. {
  193. // our month is inclusive
  194. psysTime->wYear ++;
  195. psysTime->wMonth -= 12;
  196. }
  197. dwDaysSince1970 = ElapsedYearsToDays(psysTime->wYear) - ElapsedYearsToDays(1970);
  198. // dwDaysSince1970 already included 1/1/1970
  199. dwDaysSince1970 += psysTime->wDay - 1;
  200. if(IsLeapYear(psysTime->wYear) == TRUE)
  201. {
  202. dwDaysSince1970 += LeapYearDaysPrecedingMonth[psysTime->wMonth - 1];
  203. dwDaysSince1970--;
  204. }
  205. else
  206. {
  207. dwDaysSince1970 += NormalYearDaysPrecedingMonth[psysTime->wMonth - 1];
  208. }
  209. //
  210. // Convert days since 1980 to 100 ns since 1980
  211. ul100NsSince1601 = ConvertDaysToMilliseconds(dwDaysSince1970) * 10000 + ul100Ns;
  212. ul100NsSince1601 += (SecondsToStartOf1970.QuadPart * 10000000);
  213. ConvertInt64ToFileTime(&ul100NsSince1601, &ft);
  214. bSuccess = FileTimeToSystemTime( &ft, psysTime );
  215. if(bSuccess == TRUE && pft != NULL)
  216. {
  217. *pft = ft;
  218. }
  219. return bSuccess;
  220. }