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.

878 lines
22 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // DATETIME.CPP
  6. //
  7. // alanbos 20-Jan-00 Created.
  8. //
  9. // Defines the implementation of ISWbemDateTime
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include <stdio.h>
  14. #include <sys/timeb.h>
  15. #include <math.h>
  16. #include <time.h>
  17. #include <float.h>
  18. #include <wbemint.h>
  19. #include "DateTime.h"
  20. #define ISWILD(c) (L'*' == c)
  21. #define ISINTERVAL(c) (L':' == c)
  22. #define ISMINUS(c) (L'-' == c)
  23. #define ISPLUS(c) (L'+' == c)
  24. #define ISDOT(c) (L'.' == c)
  25. #define WILD2 L"**"
  26. #define WILD3 L"***"
  27. #define WILD4 L"****"
  28. #define WILD6 L"******"
  29. #define ASSERT_BREAK
  30. //***************************************************************************
  31. //
  32. // CWbemDateTime::CWbemDateTime
  33. //
  34. // DESCRIPTION:
  35. //
  36. // Constructor.
  37. //
  38. //***************************************************************************
  39. CWbemDateTime::CWbemDateTime() :
  40. m_bYearSpecified (VARIANT_TRUE),
  41. m_bMonthSpecified (VARIANT_TRUE),
  42. m_bDaySpecified (VARIANT_TRUE),
  43. m_bHoursSpecified (VARIANT_TRUE),
  44. m_bMinutesSpecified (VARIANT_TRUE),
  45. m_bSecondsSpecified (VARIANT_TRUE),
  46. m_bMicrosecondsSpecified (VARIANT_TRUE),
  47. m_bUTCSpecified (VARIANT_TRUE),
  48. m_bIsInterval (VARIANT_FALSE),
  49. m_iYear (0),
  50. m_iMonth (1),
  51. m_iDay (1),
  52. m_iHours (0),
  53. m_iMinutes (0),
  54. m_iSeconds (0),
  55. m_iMicroseconds (0),
  56. m_iUTC (0)
  57. {
  58. }
  59. //***************************************************************************
  60. //
  61. // CWbemDateTime::~CWbemDateTime
  62. //
  63. // DESCRIPTION:
  64. //
  65. // Destructor.
  66. //
  67. //***************************************************************************
  68. CWbemDateTime::~CWbemDateTime(void)
  69. {
  70. }
  71. // These are here rather than wbemtime.h so we don't have to doc/support
  72. #define INVALID_TIME_ARITHMETIC 0
  73. #define BAD_TIMEZONE 0
  74. static int CompareSYSTEMTIME(const SYSTEMTIME *pst1, const SYSTEMTIME *pst2)
  75. {
  76. FILETIME ft1, ft2;
  77. SystemTimeToFileTime(pst1, &ft1);
  78. SystemTimeToFileTime(pst2, &ft2);
  79. return CompareFileTime(&ft1, &ft2);
  80. }
  81. //***************************************************************************
  82. //
  83. // SCODE CWbemDateTime::get_Value
  84. //
  85. // DESCRIPTION:
  86. //
  87. // Retrieve the DMTF datetime value
  88. //
  89. // PARAMETERS:
  90. //
  91. // pbsValue pointer to BSTR to hold value on return
  92. //
  93. // RETURN VALUES:
  94. //
  95. // WBEM_S_NO_ERROR success
  96. // WBEM_E_INVALID_PARAMETER bad input parameters
  97. // WBEM_E_FAILED otherwise
  98. //
  99. //***************************************************************************
  100. HRESULT CWbemDateTime :: GetValue ( BSTR *pbsValue)
  101. {
  102. HRESULT hr = WBEM_E_FAILED;
  103. if (NULL == pbsValue)
  104. hr = WBEM_E_INVALID_PARAMETER;
  105. else
  106. {
  107. wchar_t dmtfValue [WBEMDT_DMTF_LEN + 1];
  108. int dmtfLength = sizeof dmtfValue / sizeof dmtfValue[0];
  109. dmtfValue [WBEMDT_DMTF_LEN] = NULL;
  110. if (m_bIsInterval)
  111. {
  112. // Intervals are easy
  113. hr = StringCchPrintf (dmtfValue, dmtfLength , L"%08d%02d%02d%02d.%06d:000", m_iDay,
  114. m_iHours, m_iMinutes, m_iSeconds, m_iMicroseconds);
  115. }
  116. else
  117. {
  118. if (m_bYearSpecified)
  119. hr = StringCchPrintf(dmtfValue, dmtfLength , L"%04d", m_iYear);
  120. else
  121. hr = StringCchCopyW (dmtfValue, dmtfLength, WILD4);
  122. if (m_bMonthSpecified)
  123. hr = StringCchPrintf (dmtfValue + 4, dmtfLength-4, L"%02d", m_iMonth);
  124. else
  125. hr = StringCchCatW (dmtfValue + 4, dmtfLength-4, WILD2);
  126. if (m_bDaySpecified)
  127. hr = StringCchPrintf (dmtfValue + 6, dmtfLength-6, L"%02d", m_iDay);
  128. else
  129. hr = StringCchCatW (dmtfValue + 6, dmtfLength-6, WILD2);
  130. if (m_bHoursSpecified)
  131. hr = StringCchPrintf (dmtfValue + 8, dmtfLength-8, L"%02d", m_iHours);
  132. else
  133. hr = StringCchCatW (dmtfValue + 8, dmtfLength-8, WILD2);
  134. if (m_bMinutesSpecified)
  135. hr = StringCchPrintf (dmtfValue + 10, dmtfLength - 10, L"%02d", m_iMinutes);
  136. else
  137. hr = StringCchCatW (dmtfValue + 10, dmtfLength-10, WILD2);
  138. if (m_bSecondsSpecified)
  139. hr = StringCchPrintf (dmtfValue + 12, dmtfLength-12, L"%02d.", m_iSeconds);
  140. else
  141. {
  142. hr = StringCchCatW (dmtfValue + 12, dmtfLength-12, WILD2);
  143. hr = StringCchCatW (dmtfValue + 14, dmtfLength-14, L".");
  144. }
  145. if (m_bMicrosecondsSpecified)
  146. hr = StringCchPrintf (dmtfValue + 15, dmtfLength - 15, L"%06d", m_iMicroseconds);
  147. else
  148. hr = StringCchCatW (dmtfValue + 15, dmtfLength-15, WILD6);
  149. if (m_bUTCSpecified)
  150. hr = StringCchPrintf (dmtfValue + 21, dmtfLength-21, L"%C%03d", (0 <= m_iUTC) ? L'+' : L'-',
  151. (0 <= m_iUTC) ? m_iUTC : -m_iUTC);
  152. else
  153. {
  154. hr = StringCchCatW (dmtfValue + 21, dmtfLength-21, L"+");
  155. hr = StringCchCatW (dmtfValue + 22, dmtfLength-22, WILD3);
  156. }
  157. }
  158. if (SUCCEEDED(hr))
  159. {
  160. *pbsValue = SysAllocString (dmtfValue);
  161. if ( *pbsValue == NULL )
  162. {
  163. hr = WBEM_E_OUT_OF_MEMORY ;
  164. }
  165. else
  166. {
  167. hr = WBEM_S_NO_ERROR;
  168. }
  169. }
  170. }
  171. return hr;
  172. }
  173. //***************************************************************************
  174. //
  175. // SCODE CWbemDateTime::put_Value
  176. //
  177. // DESCRIPTION:
  178. //
  179. // Retrieve the DMTF datetime value
  180. //
  181. // PARAMETERS:
  182. //
  183. // bsValue new value
  184. //
  185. // RETURN VALUES:
  186. //
  187. // WBEM_S_NO_ERROR success
  188. // WBEM_E_INVALID_PARAMETER bad input parameters
  189. // WBEM_E_FAILED otherwise
  190. //
  191. //***************************************************************************
  192. HRESULT CWbemDateTime::PutValue( BSTR bsValue)
  193. {
  194. HRESULT hr = WBEM_E_INVALID_SYNTAX;
  195. // First check that the value is the right length
  196. if (bsValue && (WBEMDT_DMTF_LEN == wcslen (bsValue)))
  197. {
  198. bool err = false;
  199. long iYear = 0, iMonth = 1, iDay = 1, iHours = 0, iMinutes = 0,
  200. iSeconds = 0, iMicroseconds = 0, iUTC = 0;
  201. VARIANT_BOOL bYearSpecified = VARIANT_TRUE,
  202. bMonthSpecified = VARIANT_TRUE,
  203. bDaySpecified = VARIANT_TRUE,
  204. bHoursSpecified = VARIANT_TRUE,
  205. bMinutesSpecified = VARIANT_TRUE,
  206. bSecondsSpecified = VARIANT_TRUE,
  207. bMicrosecondsSpecified = VARIANT_TRUE,
  208. bUTCSpecified = VARIANT_TRUE,
  209. bIsInterval = VARIANT_TRUE;
  210. LPWSTR pValue = (LPWSTR) bsValue;
  211. // Check whether its an interval
  212. if (ISINTERVAL(pValue [WBEMDT_DMTF_UPOS]))
  213. {
  214. // Years and months are as nothing to us in interval land
  215. bYearSpecified = VARIANT_FALSE;
  216. bMonthSpecified = VARIANT_FALSE;
  217. // Check that everything is a digit apart from
  218. // the interval separator
  219. for (int i = 0; i < WBEMDT_DMTF_LEN; i++)
  220. {
  221. if ((WBEMDT_DMTF_UPOS != i) &&
  222. (WBEMDT_DMTF_SPOS != i) && !wbem_iswdigit (pValue [i]))
  223. {
  224. err = true;
  225. break;
  226. }
  227. }
  228. if (!err)
  229. {
  230. // Now check all is within bounds
  231. err = !(CheckField (pValue, 8, bDaySpecified, iDay, WBEMDT_MAX_DAYINT, WBEMDT_MIN_DAYINT) &&
  232. (VARIANT_TRUE == bDaySpecified) &&
  233. CheckField (pValue+8, 2, bHoursSpecified, iHours, WBEMDT_MAX_HOURS, WBEMDT_MIN_HOURS) &&
  234. (VARIANT_TRUE == bHoursSpecified) &&
  235. CheckField (pValue+10, 2, bMinutesSpecified, iMinutes, WBEMDT_MAX_MINUTES, WBEMDT_MIN_MINUTES) &&
  236. (VARIANT_TRUE == bMinutesSpecified) &&
  237. CheckField (pValue+12, 2, bSecondsSpecified, iSeconds, WBEMDT_MAX_SECONDS, WBEMDT_MIN_SECONDS) &&
  238. (VARIANT_TRUE == bSecondsSpecified) &&
  239. (ISDOT(pValue [WBEMDT_DMTF_SPOS])) &&
  240. CheckField (pValue+15, 6, bMicrosecondsSpecified, iMicroseconds, WBEMDT_MAX_MICROSEC, WBEMDT_MIN_MICROSEC) &&
  241. (VARIANT_TRUE == bMicrosecondsSpecified) &&
  242. CheckUTC (pValue+21, bUTCSpecified, iUTC, false));
  243. }
  244. }
  245. else
  246. {
  247. // assume it's a datetime
  248. bIsInterval = VARIANT_FALSE;
  249. err = !(CheckField (pValue, 4, bYearSpecified, iYear, WBEMDT_MAX_YEAR, WBEMDT_MIN_YEAR) &&
  250. CheckField (pValue+4, 2, bMonthSpecified, iMonth, WBEMDT_MAX_MONTH, WBEMDT_MIN_MONTH) &&
  251. CheckField (pValue+6, 2, bDaySpecified, iDay, WBEMDT_MAX_DAY, WBEMDT_MIN_DAY) &&
  252. CheckField (pValue+8, 2, bHoursSpecified, iHours, WBEMDT_MAX_HOURS, WBEMDT_MIN_HOURS) &&
  253. CheckField (pValue+10, 2, bMinutesSpecified, iMinutes, WBEMDT_MAX_MINUTES, WBEMDT_MIN_MINUTES) &&
  254. CheckField (pValue+12, 2, bSecondsSpecified, iSeconds, WBEMDT_MAX_SECONDS, WBEMDT_MIN_SECONDS) &&
  255. (ISDOT(pValue [WBEMDT_DMTF_SPOS])) &&
  256. CheckField (pValue+15, 6, bMicrosecondsSpecified, iMicroseconds, WBEMDT_MAX_MICROSEC, WBEMDT_MIN_MICROSEC) &&
  257. CheckUTC (pValue+21, bUTCSpecified, iUTC));
  258. }
  259. if (!err)
  260. {
  261. m_iYear = iYear;
  262. m_iMonth = iMonth;
  263. m_iDay = iDay;
  264. m_iHours = iHours;
  265. m_iMinutes = iMinutes;
  266. m_iSeconds = iSeconds;
  267. m_iMicroseconds = iMicroseconds;
  268. m_iUTC = iUTC;
  269. m_bYearSpecified = bYearSpecified;
  270. m_bMonthSpecified = bMonthSpecified;
  271. m_bDaySpecified = bDaySpecified;
  272. m_bHoursSpecified = bHoursSpecified;
  273. m_bMinutesSpecified = bMinutesSpecified;
  274. m_bSecondsSpecified = bSecondsSpecified;
  275. m_bMicrosecondsSpecified = bMicrosecondsSpecified;
  276. m_bUTCSpecified = bUTCSpecified;
  277. m_bIsInterval = bIsInterval;
  278. hr = S_OK;
  279. }
  280. }
  281. return hr;
  282. }
  283. //***************************************************************************
  284. //
  285. // SCODE CWbemDateTime::CheckField
  286. //
  287. // DESCRIPTION:
  288. //
  289. // Check a string-based datetime field for correctness
  290. //
  291. // PARAMETERS:
  292. //
  293. // pValue pointer to the value to check
  294. // len number of characters in the value
  295. // bIsSpecified on return defines whether value is wildcard
  296. // iValue on return specifies integer value (if not wildcard)
  297. // maxValue maximum numeric value allowed for this field
  298. // minValue minimum numeric value allowed for this field
  299. //
  300. // RETURN VALUES:
  301. //
  302. // true if value parsed ok, false otherwise
  303. //
  304. //***************************************************************************
  305. bool CWbemDateTime::CheckField (
  306. LPWSTR pValue,
  307. ULONG len,
  308. VARIANT_BOOL &bIsSpecified,
  309. long &iValue,
  310. long maxValue,
  311. long minValue
  312. )
  313. {
  314. bool status = true;
  315. bIsSpecified = VARIANT_FALSE;
  316. for (ULONG i = 0; i < len; i++)
  317. {
  318. if (ISWILD(pValue [i]))
  319. {
  320. if (VARIANT_TRUE == bIsSpecified)
  321. {
  322. status = false;
  323. break;
  324. }
  325. }
  326. else if (!wbem_iswdigit (pValue [i]))
  327. {
  328. status = false;
  329. break;
  330. }
  331. else
  332. bIsSpecified = VARIANT_TRUE;
  333. }
  334. if (status)
  335. {
  336. if (VARIANT_TRUE == bIsSpecified)
  337. {
  338. wchar_t *dummy = NULL;
  339. wchar_t temp [ 12 ] ;
  340. if ( len > ( ( sizeof ( temp ) / sizeof ( wchar_t ) ) - 1 ) )
  341. {
  342. return false ;
  343. }
  344. if ( FAILED ( StringCchCopyNW ( temp , ( sizeof ( temp ) / sizeof ( wchar_t ) ) , pValue, len ) ) )
  345. {
  346. return false ;
  347. }
  348. temp [ len ] = NULL ;
  349. iValue = wcstol ( temp , &dummy , 10 ) ;
  350. }
  351. }
  352. return status;
  353. }
  354. //***************************************************************************
  355. //
  356. // SCODE CWbemDateTime::CheckUTC
  357. //
  358. // DESCRIPTION:
  359. //
  360. // Check a string-based UTC field for correctness
  361. //
  362. // PARAMETERS:
  363. //
  364. // pValue pointer to the value to check
  365. // bIsSpecified on return defines whether value is wildcard
  366. // iValue on return specifies integer value (if not wildcard)
  367. // bParseSign whether first character should be a sign (+/-) or
  368. // a : (for intervals)
  369. //
  370. // RETURN VALUES:
  371. //
  372. // true if value parsed ok, false otherwise
  373. //
  374. //***************************************************************************
  375. bool CWbemDateTime::CheckUTC (
  376. LPWSTR pValue,
  377. VARIANT_BOOL &bIsSpecified,
  378. long &iValue,
  379. bool bParseSign
  380. )
  381. {
  382. bool status = true;
  383. bool lessThanZero = false;
  384. bIsSpecified = VARIANT_FALSE;
  385. // Check if we have a signed offset
  386. if (bParseSign)
  387. {
  388. if (ISMINUS(pValue [0]))
  389. lessThanZero = true;
  390. else if (!ISPLUS(pValue [0]))
  391. status = false;
  392. }
  393. else
  394. {
  395. if (!ISINTERVAL(pValue[0]))
  396. status = false;
  397. }
  398. if (status)
  399. {
  400. // Check remaining are digits or wildcars
  401. for (int i = 1; i < 4; i++)
  402. {
  403. if (ISWILD(pValue [i]))
  404. {
  405. if (VARIANT_TRUE == bIsSpecified)
  406. {
  407. status = false;
  408. break;
  409. }
  410. }
  411. else if (!wbem_iswdigit (pValue [i]))
  412. {
  413. status = false;
  414. break;
  415. }
  416. else
  417. bIsSpecified = VARIANT_TRUE;
  418. }
  419. }
  420. if (status)
  421. {
  422. if (VARIANT_TRUE == bIsSpecified)
  423. {
  424. wchar_t *dummy = NULL;
  425. wchar_t temp [4];
  426. wcsncpy (temp, pValue+1, 3);
  427. temp [3] = NULL;
  428. iValue = wcstol (temp, &dummy, 10);
  429. if (lessThanZero)
  430. iValue = -iValue;
  431. }
  432. }
  433. return status;
  434. }
  435. BOOL CWbemDateTime::Preceeds ( CWbemDateTime &a_Time )
  436. {
  437. BOOL t_Truth = TRUE ;
  438. SYSTEMTIME t_ThisTime ;
  439. t_ThisTime.wYear = ( WORD ) m_iYear;
  440. t_ThisTime.wMonth = ( WORD ) m_iMonth;
  441. t_ThisTime.wDay = ( WORD ) m_iDay;
  442. t_ThisTime.wHour = ( WORD ) m_iHours;
  443. t_ThisTime.wMinute = ( WORD ) m_iMinutes;
  444. t_ThisTime.wSecond = ( WORD ) m_iSeconds;
  445. t_ThisTime.wMilliseconds = ( WORD ) ( m_iMicroseconds/1000 ) ;
  446. SYSTEMTIME t_ArgTime ;
  447. t_ArgTime.wYear = ( WORD ) a_Time.m_iYear;
  448. t_ArgTime.wMonth = ( WORD ) a_Time.m_iMonth;
  449. t_ArgTime.wDay = ( WORD ) a_Time.m_iDay;
  450. t_ArgTime.wHour = ( WORD ) a_Time.m_iHours;
  451. t_ArgTime.wMinute = ( WORD ) a_Time.m_iMinutes;
  452. t_ArgTime.wSecond = ( WORD ) a_Time.m_iSeconds;
  453. t_ArgTime.wMilliseconds = ( WORD ) ( a_Time.m_iMicroseconds/1000 ) ;
  454. t_Truth = CompareSYSTEMTIME ( & t_ThisTime , & t_ArgTime ) < 0 ;
  455. return t_Truth ;
  456. }
  457. HRESULT CWbemDateTime::GetSystemTimeDate (
  458. SYSTEMTIME &fSystemTime
  459. )
  460. {
  461. ZeroMemory ( & fSystemTime , sizeof ( fSystemTime ) ) ;
  462. fSystemTime.wYear = ( WORD ) m_iYear;
  463. fSystemTime.wMonth = ( WORD ) m_iMonth;
  464. fSystemTime.wDay = ( WORD ) m_iDay;
  465. fSystemTime.wHour = ( WORD ) m_iHours;
  466. fSystemTime.wMinute = ( WORD ) m_iMinutes;
  467. fSystemTime.wSecond = ( WORD ) m_iSeconds;
  468. fSystemTime.wMilliseconds = ( WORD ) ( m_iMicroseconds/1000 ) ;
  469. return S_OK ;
  470. }
  471. HRESULT CWbemDateTime::GetFileTimeDate (
  472. FILETIME &fFileTime
  473. )
  474. {
  475. SYSTEMTIME fSystemTime ;
  476. ZeroMemory ( & fSystemTime , sizeof ( fSystemTime ) ) ;
  477. fSystemTime.wYear = ( WORD ) m_iYear;
  478. fSystemTime.wMonth = ( WORD ) m_iMonth;
  479. fSystemTime.wDay = ( WORD ) m_iDay;
  480. fSystemTime.wHour = ( WORD ) m_iHours;
  481. fSystemTime.wMinute = ( WORD ) m_iMinutes;
  482. fSystemTime.wSecond = ( WORD ) m_iSeconds;
  483. fSystemTime.wMilliseconds = ( WORD ) ( m_iMicroseconds/1000 ) ;
  484. if ( FileTimeToSystemTime ( & fFileTime , & fSystemTime ) )
  485. {
  486. return S_OK ;
  487. }
  488. else
  489. {
  490. return WBEM_E_FAILED ;
  491. }
  492. }
  493. static void FileTimeToui64(const FILETIME *pft, ULONGLONG *p64)
  494. {
  495. *p64 = pft->dwHighDateTime;
  496. *p64 = *p64 << 32;
  497. *p64 |= pft->dwLowDateTime;
  498. }
  499. static void ui64ToFileTime(const ULONGLONG *p64,FILETIME *pft)
  500. {
  501. unsigned __int64 uTemp = *p64;
  502. pft->dwLowDateTime = (DWORD)uTemp;
  503. uTemp = uTemp >> 32;
  504. pft->dwHighDateTime = (DWORD)uTemp;
  505. }
  506. static void DayInMonthToAbsolute(SYSTEMTIME *pst, const WORD wYear)
  507. {
  508. const static int _lpdays[] = {
  509. -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  510. };
  511. const static int _days[] = {
  512. -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
  513. };
  514. SHORT shYearDay;
  515. // If this is not 0, this is not a relative date
  516. if (pst->wYear == 0)
  517. {
  518. // Was that year a leap year?
  519. BOOL bLeap = ( (( wYear % 400) == 0) || ((( wYear % 4) == 0) && (( wYear % 100) != 0)));
  520. // Figure out the day of the year for the first day of the month in question
  521. if (bLeap)
  522. shYearDay = 1 + _lpdays[pst->wMonth - 1];
  523. else
  524. shYearDay = 1 + _days[pst->wMonth - 1];
  525. // Now, figure out how many leap days there have been since 1/1/1601
  526. WORD yc = wYear - 1601;
  527. WORD y4 = (yc) / 4;
  528. WORD y100 = (yc) / 100;
  529. WORD y400 = (yc) / 400;
  530. // This will tell us the day of the week for the first day of the month in question.
  531. // The '1 +' reflects the fact that 1/1/1601 was a monday (figures). You might ask,
  532. // 'why do we care what day of the week this is?' Well, I'll tell you. The way
  533. // daylight savings time is defined is with things like 'the last sunday of the month
  534. // of october.' Kinda helps to know what day that is.
  535. SHORT monthdow = (1 + (yc * 365 + y4 + y400 - y100) + shYearDay) % 7;
  536. if ( monthdow < pst->wDayOfWeek )
  537. shYearDay += (pst->wDayOfWeek - monthdow) + (pst->wDay - 1) * 7;
  538. else
  539. shYearDay += (pst->wDayOfWeek - monthdow) + pst->wDay * 7;
  540. /*
  541. * May have to adjust the calculation above if week == 5 (meaning
  542. * the last instance of the day in the month). Check if yearday falls
  543. * beyond month and adjust accordingly.
  544. */
  545. if ( (pst->wDay == 5) &&
  546. (shYearDay > (bLeap ? _lpdays[pst->wMonth] :
  547. _days[pst->wMonth])) )
  548. {
  549. shYearDay -= 7;
  550. }
  551. // Now update the structure.
  552. pst->wYear = wYear;
  553. pst->wDay = shYearDay - (bLeap ? _lpdays[pst->wMonth - 1] :
  554. _days[pst->wMonth - 1]);
  555. }
  556. }
  557. CWbemDateTime::WBEMTime :: WBEMTime ( const FILETIME &ft )
  558. {
  559. FileTimeToui64(&ft, &m_uTime);
  560. }
  561. CWbemDateTime::WBEMTime CWbemDateTime::WBEMTime::operator+(const WBEMTimeSpan &uAdd) const
  562. {
  563. WBEMTime ret;
  564. if (IsOk())
  565. {
  566. ret.m_uTime = m_uTime + uAdd.m_Time;
  567. }
  568. else
  569. {
  570. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  571. }
  572. return ret;
  573. }
  574. CWbemDateTime::WBEMTime CWbemDateTime::WBEMTime::operator-(const WBEMTimeSpan & sub) const
  575. {
  576. WBEMTime ret;
  577. if (IsOk() && (m_uTime >= sub.m_Time))
  578. {
  579. ret.m_uTime = m_uTime - sub.m_Time;
  580. }
  581. else
  582. {
  583. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  584. }
  585. return ret;
  586. }
  587. BOOL CWbemDateTime::WBEMTime::GetFILETIME(FILETIME * pft) const
  588. {
  589. if ((pft == NULL) || (!IsOk()))
  590. {
  591. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  592. return FALSE;
  593. }
  594. ui64ToFileTime(&m_uTime, pft);
  595. return TRUE;
  596. }
  597. LONG CWbemDateTime::WBEMTime::GetLocalOffsetForDate(const SYSTEMTIME *pst)
  598. {
  599. TIME_ZONE_INFORMATION tzTime;
  600. DWORD dwRes = GetTimeZoneInformation(&tzTime);
  601. LONG lRes = 0xffffffff;
  602. switch (dwRes)
  603. {
  604. case TIME_ZONE_ID_UNKNOWN:
  605. {
  606. // Read tz, but no dst defined in this zone
  607. lRes = tzTime.Bias * -1;
  608. break;
  609. }
  610. case TIME_ZONE_ID_STANDARD:
  611. case TIME_ZONE_ID_DAYLIGHT:
  612. {
  613. // Convert the relative dates to absolute dates
  614. DayInMonthToAbsolute(&tzTime.DaylightDate, pst->wYear);
  615. DayInMonthToAbsolute(&tzTime.StandardDate, pst->wYear);
  616. if ( CompareSYSTEMTIME(&tzTime.DaylightDate, &tzTime.StandardDate) < 0 )
  617. {
  618. /*
  619. * Northern hemisphere ordering
  620. */
  621. if ( CompareSYSTEMTIME(pst, &tzTime.DaylightDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.StandardDate) > 0)
  622. {
  623. lRes = tzTime.Bias * -1;
  624. }
  625. else
  626. {
  627. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  628. }
  629. }
  630. else
  631. {
  632. /*
  633. * Southern hemisphere ordering
  634. */
  635. if ( CompareSYSTEMTIME(pst, &tzTime.StandardDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.DaylightDate) > 0)
  636. {
  637. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  638. }
  639. else
  640. {
  641. lRes = tzTime.Bias * -1;
  642. }
  643. }
  644. break;
  645. }
  646. case TIME_ZONE_ID_INVALID:
  647. default:
  648. {
  649. // Can't read the timezone info
  650. ASSERT_BREAK(BAD_TIMEZONE);
  651. break;
  652. }
  653. }
  654. return lRes;
  655. }
  656. BOOL CWbemDateTime::WBEMTime::GetDMTF(SYSTEMTIME &st, long &offset) const
  657. {
  658. if (!IsOk())
  659. {
  660. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  661. return FALSE;
  662. }
  663. // If the date to be converted is within 12 hours of
  664. // 1/1/1601, return the greenwich time
  665. ULONGLONG t_ConversionZone = 12L * 60L * 60L ;
  666. t_ConversionZone = t_ConversionZone * 10000000L ;
  667. if ( m_uTime < t_ConversionZone )
  668. {
  669. if(!GetSYSTEMTIME(&st))
  670. return FALSE;
  671. }
  672. else
  673. {
  674. if (GetSYSTEMTIME(&st))
  675. {
  676. offset = GetLocalOffsetForDate(&st);
  677. WBEMTime wt;
  678. if (offset >= 0)
  679. wt = *this - WBEMTimeSpan(offset);
  680. else
  681. wt = *this + WBEMTimeSpan(-offset);
  682. wt.GetSYSTEMTIME(&st);
  683. }
  684. else
  685. return FALSE;
  686. }
  687. return TRUE ;
  688. }
  689. BOOL CWbemDateTime::WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst) const
  690. {
  691. if ((pst == NULL) || (!IsOk()))
  692. {
  693. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  694. return FALSE;
  695. }
  696. FILETIME t_ft;
  697. if (GetFILETIME(&t_ft))
  698. {
  699. if (!FileTimeToSystemTime(&t_ft, pst))
  700. {
  701. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  702. return FALSE;
  703. }
  704. }
  705. else
  706. {
  707. return FALSE;
  708. }
  709. return TRUE;
  710. }
  711. //***************************************************************************
  712. //
  713. // SCODE CWbemDateTime::SetVarDate
  714. //
  715. // DESCRIPTION:
  716. //
  717. // Set the value in Variant form
  718. //
  719. // PARAMETERS:
  720. //
  721. // dVarDate the new value
  722. // bIsLocal whether to treat as local or UTC value
  723. //
  724. // RETURN VALUES:
  725. //
  726. // WBEM_S_NO_ERROR success
  727. // WBEM_E_INVALID_SYNTAX input value is bad
  728. //
  729. //***************************************************************************
  730. HRESULT CWbemDateTime::SetFileTimeDate(
  731. /*[in]*/ FILETIME fFileTime,
  732. /*[in, optional]*/ VARIANT_BOOL bIsLocal)
  733. {
  734. HRESULT hr = WBEM_E_INVALID_SYNTAX;
  735. SYSTEMTIME sysTime;
  736. long offset = 0;
  737. if (VARIANT_TRUE == bIsLocal)
  738. {
  739. WBEMTime wbemTime (fFileTime);
  740. if (!wbemTime.GetDMTF (sysTime, offset))
  741. return WBEM_E_INVALID_SYNTAX;
  742. }
  743. else
  744. {
  745. WBEMTime wbemTime (fFileTime);
  746. wbemTime.GetSYSTEMTIME(&sysTime);
  747. }
  748. m_iYear = sysTime.wYear;
  749. m_iMonth = sysTime.wMonth;
  750. m_iDay = sysTime.wDay;
  751. m_iHours = sysTime.wHour;
  752. m_iMinutes = sysTime.wMinute;
  753. m_iSeconds = sysTime.wSecond;
  754. m_iMicroseconds = sysTime.wMilliseconds * 1000;
  755. m_iUTC = offset;
  756. m_bYearSpecified = VARIANT_TRUE,
  757. m_bMonthSpecified = VARIANT_TRUE,
  758. m_bDaySpecified = VARIANT_TRUE,
  759. m_bHoursSpecified = VARIANT_TRUE,
  760. m_bMinutesSpecified = VARIANT_TRUE,
  761. m_bSecondsSpecified = VARIANT_TRUE,
  762. m_bMicrosecondsSpecified = VARIANT_TRUE,
  763. m_bUTCSpecified = VARIANT_TRUE,
  764. m_bIsInterval = VARIANT_FALSE;
  765. hr = S_OK;
  766. return hr;
  767. }