Leaked source code of windows server 2003
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.

399 lines
10 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. WBEMTIME.CPP
  5. Abstract:
  6. Time helper
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include "CWbemTime.h"
  11. #include <stdio.h>
  12. static void i64ToFileTime( const __int64 *p64, FILETIME *pft )
  13. {
  14. __int64 iTemp = *p64;
  15. pft->dwLowDateTime = (DWORD)iTemp;
  16. iTemp = iTemp >> 32;
  17. pft->dwHighDateTime = (DWORD)iTemp;
  18. }
  19. static int CompareSYSTEMTIME(const SYSTEMTIME *pst1, const SYSTEMTIME *pst2)
  20. {
  21. FILETIME ft1, ft2;
  22. SystemTimeToFileTime(pst1, &ft1);
  23. SystemTimeToFileTime(pst2, &ft2);
  24. return CompareFileTime(&ft1, &ft2);
  25. }
  26. // This function is used to convert the relative values that come
  27. // back from GetTimeZoneInformation into an actual date for the year
  28. // in question. The system time structure that is passed in is updated
  29. // to contain the absolute values.
  30. static void DayInMonthToAbsolute(SYSTEMTIME *pst, const WORD wYear)
  31. {
  32. const static int _lpdays[] = {
  33. -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  34. };
  35. const static int _days[] = {
  36. -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
  37. };
  38. SHORT shYearDay;
  39. // If this is not 0, this is not a relative date
  40. if (pst->wYear == 0)
  41. {
  42. // Was that year a leap year?
  43. BOOL bLeap = ( (( wYear % 400) == 0) || ((( wYear % 4) == 0) && (( wYear % 100) != 0)));
  44. // Figure out the day of the year for the first day of the month in question
  45. if (bLeap)
  46. shYearDay = 1 + _lpdays[pst->wMonth - 1];
  47. else
  48. shYearDay = 1 + _days[pst->wMonth - 1];
  49. // Now, figure out how many leap days there have been since 1/1/1601
  50. WORD yc = wYear - 1601;
  51. WORD y4 = (yc) / 4;
  52. WORD y100 = (yc) / 100;
  53. WORD y400 = (yc) / 400;
  54. // This will tell us the day of the week for the first day of the month in question.
  55. // The '1 +' reflects the fact that 1/1/1601 was a monday (figures). You might ask,
  56. // 'why do we care what day of the week this is?' Well, I'll tell you. The way
  57. // daylight savings time is defined is with things like 'the last sunday of the month
  58. // of october.' Kinda helps to know what day that is.
  59. SHORT monthdow = (1 + (yc * 365 + y4 + y400 - y100) + shYearDay) % 7;
  60. if ( monthdow < pst->wDayOfWeek )
  61. shYearDay += (pst->wDayOfWeek - monthdow) + (pst->wDay - 1) * 7;
  62. else
  63. shYearDay += (pst->wDayOfWeek - monthdow) + pst->wDay * 7;
  64. /*
  65. * May have to adjust the calculation above if week == 5 (meaning
  66. * the last instance of the day in the month). Check if yearday falls
  67. * beyond month and adjust accordingly.
  68. */
  69. if ( (pst->wDay == 5) &&
  70. (shYearDay > (bLeap ? _lpdays[pst->wMonth] :
  71. _days[pst->wMonth])) )
  72. {
  73. shYearDay -= 7;
  74. }
  75. // Now update the structure.
  76. pst->wYear = wYear;
  77. pst->wDay = shYearDay - (bLeap ? _lpdays[pst->wMonth - 1] :
  78. _days[pst->wMonth - 1]);
  79. }
  80. }
  81. CWbemTime CWbemTime::GetCurrentTime()
  82. {
  83. SYSTEMTIME st;
  84. ::GetSystemTime(&st);
  85. CWbemTime CurrentTime;
  86. CurrentTime.SetSystemTime(st);
  87. return CurrentTime;
  88. }
  89. BOOL CWbemTime::SetSystemTime(const SYSTEMTIME& st)
  90. {
  91. FILETIME ft;
  92. if(!SystemTimeToFileTime(&st, &ft))
  93. return FALSE;
  94. __int64 i64Time = ft.dwHighDateTime;
  95. i64Time = (i64Time << 32) + ft.dwLowDateTime;
  96. Set100nss(i64Time);
  97. return TRUE;
  98. }
  99. BOOL CWbemTime::SetFileTime(const FILETIME& ft)
  100. {
  101. __int64 i64Time = ft.dwHighDateTime;
  102. i64Time = (i64Time << 32) + ft.dwLowDateTime;
  103. Set100nss(i64Time);
  104. return TRUE;
  105. }
  106. BOOL CWbemTime::GetSYSTEMTIME(SYSTEMTIME * pst) const
  107. {
  108. FILETIME t_ft;
  109. if (GetFILETIME(&t_ft))
  110. {
  111. if (!FileTimeToSystemTime(&t_ft, pst))
  112. {
  113. return FALSE;
  114. }
  115. }
  116. else
  117. {
  118. return FALSE;
  119. }
  120. return TRUE;
  121. }
  122. BOOL CWbemTime::GetFILETIME(FILETIME * pft) const
  123. {
  124. if ( pft == NULL )
  125. {
  126. return FALSE;
  127. }
  128. i64ToFileTime( &m_i64, pft );
  129. return TRUE;
  130. }
  131. CWbemInterval CWbemTime::RemainsUntil(const CWbemTime& Other) const
  132. {
  133. __int64 i64Diff = Other.m_i64 - m_i64;
  134. if(i64Diff < 0) i64Diff = 0;
  135. return CWbemInterval((DWORD)(i64Diff/10000));
  136. }
  137. CWbemTime CWbemTime::operator+(const CWbemInterval& ToAdd) const
  138. {
  139. return CWbemTime(m_i64 + 10000*(__int64)ToAdd.GetMilliseconds());
  140. }
  141. BOOL CWbemTime::SetDMTF(LPCWSTR wszText)
  142. {
  143. if(wcslen(wszText) != 25)
  144. return FALSE;
  145. // Parse it
  146. // ========
  147. int nYear, nMonth, nDay, nHour, nMinute, nSecond, nMicro, nOffset;
  148. WCHAR wchSep;
  149. int nRes = swscanf(wszText, L"%4d%2d%2d%2d%2d%2d.%6d%c%3d",
  150. &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond, &nMicro,
  151. &wchSep, &nOffset);
  152. if(nRes != 9)
  153. return FALSE;
  154. int nSign;
  155. if(wchSep == L'+')
  156. nSign = -1;
  157. else if(wchSep == L'-')
  158. nSign = 1;
  159. else if(wchSep == L':')
  160. nSign = 0;
  161. else
  162. return FALSE;
  163. // Convert it to SYSTEMTIME
  164. // ========================
  165. SYSTEMTIME st;
  166. st.wYear = (WORD)nYear;
  167. st.wMonth = (WORD)nMonth;
  168. st.wDay = (WORD)nDay;
  169. st.wHour = (WORD)nHour;
  170. st.wMinute = (WORD)nMinute;
  171. st.wSecond = (WORD)nSecond;
  172. st.wMilliseconds = nMicro / 1000;
  173. // NOTE: ignored timezone for now
  174. // ==============================
  175. if(!SetSystemTime(st))
  176. return FALSE;
  177. // Now adjust for the offset
  178. // =========================
  179. m_i64 += (__int64)nSign * (__int64)nOffset * 60 * 10000000;
  180. return TRUE;
  181. }
  182. LONG CWbemTime::GetLocalOffsetForDate(const SYSTEMTIME *pst)
  183. {
  184. TIME_ZONE_INFORMATION tzTime;
  185. DWORD dwRes = GetTimeZoneInformation(&tzTime);
  186. LONG lRes = 0xffffffff;
  187. switch (dwRes)
  188. {
  189. case TIME_ZONE_ID_UNKNOWN:
  190. {
  191. // Read tz, but no dst defined in this zone
  192. lRes = tzTime.Bias * -1;
  193. break;
  194. }
  195. case TIME_ZONE_ID_STANDARD:
  196. case TIME_ZONE_ID_DAYLIGHT:
  197. {
  198. // Convert the relative dates to absolute dates
  199. DayInMonthToAbsolute(&tzTime.DaylightDate, pst->wYear);
  200. DayInMonthToAbsolute(&tzTime.StandardDate, pst->wYear);
  201. if ( CompareSYSTEMTIME(&tzTime.DaylightDate, &tzTime.StandardDate) < 0 )
  202. {
  203. /*
  204. * Northern hemisphere ordering
  205. */
  206. if ( CompareSYSTEMTIME(pst, &tzTime.DaylightDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.StandardDate) > 0)
  207. {
  208. lRes = tzTime.Bias * -1;
  209. }
  210. else
  211. {
  212. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  213. }
  214. }
  215. else
  216. {
  217. /*
  218. * Southern hemisphere ordering
  219. */
  220. if ( CompareSYSTEMTIME(pst, &tzTime.StandardDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.DaylightDate) > 0)
  221. {
  222. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  223. }
  224. else
  225. {
  226. lRes = tzTime.Bias * -1;
  227. }
  228. }
  229. break;
  230. }
  231. case TIME_ZONE_ID_INVALID:
  232. default:
  233. {
  234. // Can't read the timezone info
  235. //ASSERT_BREAK(BAD_TIMEZONE);
  236. break;
  237. }
  238. }
  239. return lRes;
  240. }
  241. BOOL CWbemTime::GetDMTF( BOOL bLocal, DWORD dwBuffLen, LPWSTR pwszBuff )
  242. {
  243. SYSTEMTIME t_Systime;
  244. wchar_t chsign = L'-';
  245. int offset = 0;
  246. // Need to Localize the offset
  247. if ( dwBuffLen < WBEMTIME_LENGTH + 1 )
  248. {
  249. return FALSE;
  250. }
  251. // If the date to be converted is within 12 hours of
  252. // 1/1/1601, return the greenwich time
  253. ULONGLONG t_ConversionZone = 12L * 60L * 60L ;
  254. t_ConversionZone = t_ConversionZone * 10000000L ;
  255. if ( !bLocal || ( m_i64 < t_ConversionZone ) )
  256. {
  257. if(!GetSYSTEMTIME(&t_Systime))
  258. {
  259. return NULL;
  260. }
  261. }
  262. else
  263. {
  264. if (GetSYSTEMTIME(&t_Systime))
  265. {
  266. offset = GetLocalOffsetForDate(&t_Systime);
  267. CWbemTime wt;
  268. if (offset >= 0)
  269. {
  270. chsign = '+';
  271. wt = *this + CWbemTimeSpan(0, 0, offset, 0);
  272. }
  273. else
  274. {
  275. offset *= -1;
  276. wt = *this - CWbemTimeSpan(0, 0, offset, 0);
  277. }
  278. wt.GetSYSTEMTIME(&t_Systime);
  279. }
  280. else
  281. {
  282. return NULL;
  283. }
  284. }
  285. LONGLONG tmpMicros = m_i64%10000000;
  286. LONG micros = (LONG)(tmpMicros / 10);
  287. if (FAILED(StringCchPrintfW(
  288. pwszBuff, dwBuffLen,
  289. L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d%c%03.3ld",
  290. t_Systime.wYear,
  291. t_Systime.wMonth,
  292. t_Systime.wDay,
  293. t_Systime.wHour,
  294. t_Systime.wMinute,
  295. t_Systime.wSecond,
  296. micros,
  297. chsign,
  298. offset
  299. ))) return FALSE;
  300. return TRUE ;
  301. }
  302. CWbemTime CWbemTime::operator+(const CWbemTimeSpan &uAdd) const
  303. {
  304. CWbemTime ret;
  305. ret.m_i64 = m_i64 + uAdd.m_Time;
  306. return ret;
  307. }
  308. CWbemTime CWbemTime::operator-(const CWbemTimeSpan &uSub) const
  309. {
  310. CWbemTime ret;
  311. ret.m_i64 = m_i64 - uSub.m_Time;
  312. return ret;
  313. }
  314. CWbemTimeSpan::CWbemTimeSpan(int iDays, int iHours, int iMinutes, int iSeconds,
  315. int iMSec, int iUSec, int iNSec)
  316. {
  317. m_Time = 0; //todo, check values!!!
  318. m_Time += iSeconds;
  319. m_Time += iMinutes * 60;
  320. m_Time += iHours * 60 * 60;
  321. m_Time += iDays * 24 * 60 * 60;
  322. m_Time *= 10000000;
  323. m_Time += iNSec / 100; // Nanoseconds
  324. m_Time += iUSec*10; // Microseconds
  325. m_Time += iMSec*10000; // Milliseconds
  326. }