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.

247 lines
6.6 KiB

  1. #include <timeutil.h>
  2. ////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Helper Function TimeDiff(tm1, tm2)
  5. // helper function to find the difference (in seconds) of 2 system times
  6. //
  7. // Input: 2 SYSTEMTIME structures
  8. // Output: None
  9. // Return: seconds of difference
  10. // > 0 if tm2 is later than tm1
  11. // = 0 if tm2 and tm1 are the same
  12. // < 0 if tm2 is earlier than tm1
  13. //
  14. // On error the function returns 0 even if the two times are not equal
  15. //
  16. // Comment: If the number of seconds goes beyond INT_MAX (that is
  17. // more than 24,855 days, INT_MAX is returned.
  18. // If the number of seconds goes beyond INT_MIN (a negative value,
  19. // means 24,855 days ago), INT_MIN is returned.
  20. //
  21. ////////////////////////////////////////////////////////////////////////////
  22. int TimeDiff(SYSTEMTIME tm1, SYSTEMTIME tm2)
  23. {
  24. LONGLONG i64Sec;
  25. int iSec;
  26. //
  27. // convert the two times from SYSTEMTIME format into FILETIME format
  28. //
  29. FILETIME ftm1, ftm2;
  30. if ((SystemTimeToFileTime(&tm1, &ftm1) == 0) ||
  31. (SystemTimeToFileTime(&tm2, &ftm2) == 0))
  32. {
  33. return 0;
  34. }
  35. if ((ftm1.dwHighDateTime == ftm2.dwHighDateTime) &&
  36. (ftm1.dwLowDateTime == ftm2.dwLowDateTime))
  37. {
  38. return 0;
  39. }
  40. //
  41. // convert the two times from FILETIME to LARGE_INTEGER type,
  42. //
  43. LARGE_INTEGER i64Sec1, i64Sec2;
  44. i64Sec2.LowPart = ftm2.dwLowDateTime;
  45. i64Sec2.HighPart = ftm2.dwHighDateTime;
  46. i64Sec1.LowPart = ftm1.dwLowDateTime;
  47. i64Sec1.HighPart = ftm1.dwHighDateTime;
  48. //
  49. // since Windows support LONGLONG, we directly use the quad portion of LARGE_INTEGER
  50. // to get the difference, which is 100 nanoseconds. Then convert the number to seconds.
  51. //
  52. i64Sec = (i64Sec2.QuadPart - i64Sec1.QuadPart) / NanoSec100PerSec;
  53. //
  54. // convert the LONGLONG seconds value into integer, since it shouldn't exceed
  55. // integer limit
  56. //
  57. if (i64Sec > INT_MAX)
  58. {
  59. //
  60. // just in case user is playing with the system time.
  61. // Otherwise, this difference should not go beyond 68 years.
  62. //
  63. iSec = INT_MAX;
  64. }
  65. else
  66. {
  67. if (i64Sec < INT_MIN)
  68. {
  69. iSec = INT_MIN;
  70. }
  71. else
  72. {
  73. iSec = (int)i64Sec;
  74. }
  75. }
  76. return iSec;
  77. }
  78. ////////////////////////////////////////////////////////////////////////////
  79. //
  80. // Helper Function TimeAddSeconds(SYSTEMTIME, int, SYSTEMTIME* )
  81. // helper function to calculate time by adding n seconds to
  82. // the given time.
  83. //
  84. // Input: a SYSTEMTIME as base time, an int as seconds to add to the base time
  85. // Output: new time
  86. // Return: HRESULT
  87. //
  88. ////////////////////////////////////////////////////////////////////////////
  89. HRESULT TimeAddSeconds(SYSTEMTIME tmBase, int iSeconds, SYSTEMTIME* pTimeNew)
  90. {
  91. // fixcode use i64 calcs
  92. FILETIME ftm;
  93. if (SystemTimeToFileTime(&tmBase, &ftm) == 0)
  94. {
  95. return E_FAIL;
  96. }
  97. LARGE_INTEGER i64Sec;
  98. i64Sec.LowPart = ftm.dwLowDateTime;
  99. i64Sec.HighPart = ftm.dwHighDateTime;
  100. __int64 i64Delay = NanoSec100PerSec;
  101. i64Delay *= iSeconds;
  102. i64Sec.QuadPart += i64Delay;
  103. ftm.dwLowDateTime = i64Sec.LowPart;
  104. ftm.dwHighDateTime = i64Sec.HighPart;
  105. if (FileTimeToSystemTime(&ftm, pTimeNew) == 0)
  106. {
  107. return E_FAIL;
  108. }
  109. return S_OK;
  110. }
  111. //=======================================================================
  112. // String2SystemTime
  113. //=======================================================================
  114. HRESULT String2SystemTime(LPCTSTR pszDateTime, SYSTEMTIME *ptm)
  115. {
  116. // we expect the date/time format as 4-digit year ISO:
  117. // 01234567890123456789
  118. // YYYY.MM.DD HH:MM:SS
  119. //
  120. const TCHAR C_DATE_DEL = _T('.');
  121. const TCHAR C_DATE_TIME_DEL = _T(' ');
  122. const TCHAR C_TIME_DEL = _T(':');
  123. TCHAR szBuf[20];
  124. LPTSTR pszDestEnd;
  125. if (FAILED(StringCchCopyEx(szBuf, ARRAYSIZE(szBuf), pszDateTime, &pszDestEnd, NULL, MISTSAFE_STRING_FLAGS)) ||
  126. 19 != pszDestEnd - szBuf)
  127. {
  128. return E_INVALIDARG;
  129. }
  130. for (int i = 0; i < 19; i++)
  131. {
  132. switch (i)
  133. {
  134. case 4:
  135. case 7:
  136. if (szBuf[i] != C_DATE_DEL)
  137. {
  138. return E_INVALIDARG;
  139. }
  140. break;
  141. case 10:
  142. if (szBuf[i] != C_DATE_TIME_DEL)
  143. {
  144. return E_INVALIDARG;
  145. }
  146. break;
  147. case 13:
  148. case 16:
  149. if (szBuf[i] != C_TIME_DEL)
  150. {
  151. return E_INVALIDARG;
  152. }
  153. break;
  154. default:
  155. if (szBuf[i] < _T('0') || pszDateTime[i] > _T('9'))
  156. {
  157. return E_INVALIDARG;
  158. }
  159. break;
  160. }
  161. }
  162. //
  163. // get values
  164. //
  165. szBuf[4] = EOS;
  166. ptm->wYear = (short)_ttoi(szBuf);
  167. szBuf[7] = EOS;
  168. ptm->wMonth = (short)_ttoi(szBuf + 5);
  169. szBuf[10] = EOS;
  170. ptm->wDay = (short)_ttoi(szBuf + 8);
  171. szBuf[13] = EOS;
  172. ptm->wHour = (short)_ttoi(szBuf + 11);
  173. szBuf[16] = EOS;
  174. ptm->wMinute = (short)_ttoi(szBuf + 14);
  175. ptm->wSecond = (short)_ttoi(szBuf + 17);
  176. ptm->wMilliseconds = 0;
  177. //
  178. // validate if this constructed SYSTEMTIME data is good
  179. //
  180. // fixcode should this just be SystemTimeToFileTime() ?
  181. if (GetDateFormat(LOCALE_SYSTEM_DEFAULT,DATE_SHORTDATE, ptm, NULL, NULL, 0) == 0)
  182. {
  183. return E_INVALIDARG;
  184. }
  185. if (GetTimeFormat(LOCALE_SYSTEM_DEFAULT,LOCALE_NOUSEROVERRIDE, ptm, NULL, NULL, 0) == 0)
  186. {
  187. return E_INVALIDARG;
  188. }
  189. return S_OK;
  190. }
  191. //=======================================================================
  192. // SystemTime2String
  193. //=======================================================================
  194. HRESULT SystemTime2String(SYSTEMTIME & tm, LPTSTR pszDateTime, size_t cchSize)
  195. {
  196. if ( pszDateTime == NULL )
  197. {
  198. return E_INVALIDARG;
  199. }
  200. // bug fixed: changed from wsprintf to _snwprintf because an invalid
  201. // date on tm was causing buffer overflow
  202. LPTSTR pszDestEnd;
  203. if (FAILED(StringCchPrintfEx(
  204. pszDateTime,
  205. cchSize,
  206. &pszDestEnd,
  207. NULL,
  208. MISTSAFE_STRING_FLAGS,
  209. TEXT("%4i.%02i.%02i %02i:%02i:%02i"),
  210. tm.wYear,
  211. tm.wMonth,
  212. tm.wDay,
  213. tm.wHour,
  214. tm.wMinute,
  215. tm.wSecond)) ||
  216. pszDestEnd - pszDateTime != 19)
  217. {
  218. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  219. }
  220. return S_OK;
  221. }