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.

1240 lines
30 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  4. //
  5. // wbemtime.cpp
  6. //
  7. // Purpose: Defines the WBEMTime and WBEMTimeSpan objects which are
  8. // similar to the MFC CTime and CTimeSpan objects. The WBEM versions
  9. // are capable of storing down to the nsec and also have functions for
  10. // Creating from and getting BSTRs.
  11. //
  12. // Note; The current implementation of WBEMTime does not support dates
  13. // before 1/1/1601;
  14. //
  15. // WBEMTime::m_uTime is stored in GMT as 100 nsecs since 1/1/1601
  16. //
  17. //***************************************************************************
  18. #include "precomp.h"
  19. #include <stdio.h>
  20. #pragma warning( disable : 4290 )
  21. #ifdef UTILLIB
  22. #include <assertbreak.h>
  23. #else
  24. #define ASSERT_BREAK(a)
  25. #endif //UTILLIB
  26. #include <WbemTime.h>
  27. #include <comdef.h>
  28. // These are here rather than wbemtime.h so we don't have to doc/support
  29. #define DECPOS 14
  30. #define SGNPOS 21
  31. #define DMTFLEN 25
  32. #define DEPRECATED 0
  33. #define INVALID_TIME_FORMAT 0
  34. #define INVALID_TIME_ARITHMETIC 0
  35. #define BAD_TIMEZONE 0
  36. // ****************************************************************
  37. // Static functions and variables. These can't be called/referenced
  38. // outside of wbemtime.cpp
  39. static WBEMTime g_Jan1970((time_t)0);
  40. //***************************************************************************
  41. //
  42. // StructtmToSystemTime
  43. //
  44. // Description: General utility for converting between the two common
  45. // data structures.
  46. //
  47. // Return values: TRUE if OK;
  48. //
  49. //***************************************************************************
  50. static BOOL StructtmToSystemTime(const struct tm *ptm, SYSTEMTIME * pst)
  51. {
  52. if (pst && ptm)
  53. {
  54. pst->wYear = ptm->tm_year + 1900;
  55. pst->wMonth = ptm->tm_mon + 1;
  56. pst->wDay = (WORD)ptm->tm_mday;
  57. pst->wHour = (WORD)ptm->tm_hour;
  58. pst->wMinute = (WORD)ptm->tm_min;
  59. pst->wSecond = (WORD)ptm->tm_sec;
  60. pst->wDayOfWeek = (WORD)ptm->tm_wday;
  61. pst->wMilliseconds = 0;
  62. return TRUE;
  63. }
  64. return FALSE;
  65. }
  66. static BOOL SystemTimeToStructtm(const SYSTEMTIME *pst, struct tm *ptm)
  67. {
  68. if (pst && ptm && pst->wYear >= 1900)
  69. {
  70. ptm->tm_year = pst->wYear - 1900;
  71. ptm->tm_mon = pst->wMonth - 1;
  72. ptm->tm_mday = pst->wDay;
  73. ptm->tm_hour = pst->wHour;
  74. ptm->tm_min = pst->wMinute;
  75. ptm->tm_sec = pst->wSecond;
  76. ptm->tm_wday = pst->wDayOfWeek;
  77. ptm->tm_isdst = 0; // Since we are working in gmt...
  78. return TRUE;
  79. }
  80. return FALSE;
  81. }
  82. //***************************************************************************
  83. //
  84. // FileTimeToui64
  85. // ui64ToFileTime
  86. //
  87. // Description: Conversion routines for going between FILETIME structures
  88. // and __int64.
  89. //
  90. //***************************************************************************
  91. static void FileTimeToui64(const FILETIME *pft, ULONGLONG *p64)
  92. {
  93. *p64 = pft->dwHighDateTime;
  94. *p64 = *p64 << 32;
  95. *p64 |= pft->dwLowDateTime;
  96. }
  97. static void ui64ToFileTime(const ULONGLONG *p64,FILETIME *pft)
  98. {
  99. unsigned __int64 uTemp = *p64;
  100. pft->dwLowDateTime = (DWORD)uTemp;
  101. uTemp = uTemp >> 32;
  102. pft->dwHighDateTime = (DWORD)uTemp;
  103. }
  104. static int CompareSYSTEMTIME(const SYSTEMTIME *pst1, const SYSTEMTIME *pst2)
  105. {
  106. FILETIME ft1, ft2;
  107. SystemTimeToFileTime(pst1, &ft1);
  108. SystemTimeToFileTime(pst2, &ft2);
  109. return CompareFileTime(&ft1, &ft2);
  110. }
  111. // This function is used to convert the relative values that come
  112. // back from GetTimeZoneInformation into an actual date for the year
  113. // in question. The system time structure that is passed in is updated
  114. // to contain the absolute values.
  115. static void DayInMonthToAbsolute(SYSTEMTIME *pst, const WORD wYear)
  116. {
  117. const static int _lpdays[] = {
  118. -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  119. };
  120. const static int _days[] = {
  121. -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
  122. };
  123. SHORT shYearDay;
  124. // If this is not 0, this is not a relative date
  125. if (pst->wYear == 0)
  126. {
  127. // Was that year a leap year?
  128. BOOL bLeap = ( (( wYear % 400) == 0) || ((( wYear % 4) == 0) && (( wYear % 100) != 0)));
  129. // Figure out the day of the year for the first day of the month in question
  130. if (bLeap)
  131. shYearDay = 1 + _lpdays[pst->wMonth - 1];
  132. else
  133. shYearDay = 1 + _days[pst->wMonth - 1];
  134. // Now, figure out how many leap days there have been since 1/1/1601
  135. WORD yc = wYear - 1601;
  136. WORD y4 = (yc) / 4;
  137. WORD y100 = (yc) / 100;
  138. WORD y400 = (yc) / 400;
  139. // This will tell us the day of the week for the first day of the month in question.
  140. // The '1 +' reflects the fact that 1/1/1601 was a monday (figures). You might ask,
  141. // 'why do we care what day of the week this is?' Well, I'll tell you. The way
  142. // daylight savings time is defined is with things like 'the last sunday of the month
  143. // of october.' Kinda helps to know what day that is.
  144. SHORT monthdow = (1 + (yc * 365 + y4 + y400 - y100) + shYearDay) % 7;
  145. if ( monthdow < pst->wDayOfWeek )
  146. shYearDay += (pst->wDayOfWeek - monthdow) + (pst->wDay - 1) * 7;
  147. else
  148. shYearDay += (pst->wDayOfWeek - monthdow) + pst->wDay * 7;
  149. /*
  150. * May have to adjust the calculation above if week == 5 (meaning
  151. * the last instance of the day in the month). Check if yearday falls
  152. * beyond month and adjust accordingly.
  153. */
  154. if ( (pst->wDay == 5) &&
  155. (shYearDay > (bLeap ? _lpdays[pst->wMonth] :
  156. _days[pst->wMonth])) )
  157. {
  158. shYearDay -= 7;
  159. }
  160. // Now update the structure.
  161. pst->wYear = wYear;
  162. pst->wDay = shYearDay - (bLeap ? _lpdays[pst->wMonth - 1] :
  163. _days[pst->wMonth - 1]);
  164. }
  165. }
  166. // **************************************************************************
  167. // These are static to WBEMTIME, which means they CAN be called from outside
  168. // wbemtime
  169. LONG WBEMTime::GetLocalOffsetForDate(const time_t &t)
  170. {
  171. FILETIME ft;
  172. ULONGLONG ull = Int32x32To64(t, 10000000) + 116444736000000000;
  173. ui64ToFileTime(&ull, &ft);
  174. return GetLocalOffsetForDate(&ft);
  175. }
  176. LONG WBEMTime::GetLocalOffsetForDate(const struct tm *ptmin)
  177. {
  178. SYSTEMTIME st;
  179. StructtmToSystemTime(ptmin, &st);
  180. return GetLocalOffsetForDate(&st);
  181. }
  182. LONG WBEMTime::GetLocalOffsetForDate(const FILETIME *pft)
  183. {
  184. SYSTEMTIME st;
  185. FileTimeToSystemTime(pft, &st);
  186. return GetLocalOffsetForDate(&st);
  187. }
  188. LONG WBEMTime::GetLocalOffsetForDate(const SYSTEMTIME *pst)
  189. {
  190. TIME_ZONE_INFORMATION tzTime;
  191. DWORD dwRes = GetTimeZoneInformation(&tzTime);
  192. LONG lRes = 0xffffffff;
  193. switch (dwRes)
  194. {
  195. case TIME_ZONE_ID_UNKNOWN:
  196. {
  197. // Read tz, but no dst defined in this zone
  198. lRes = tzTime.Bias * -1;
  199. break;
  200. }
  201. case TIME_ZONE_ID_STANDARD:
  202. case TIME_ZONE_ID_DAYLIGHT:
  203. {
  204. // Convert the relative dates to absolute dates
  205. DayInMonthToAbsolute(&tzTime.DaylightDate, pst->wYear);
  206. DayInMonthToAbsolute(&tzTime.StandardDate, pst->wYear);
  207. if ( CompareSYSTEMTIME(&tzTime.DaylightDate, &tzTime.StandardDate) < 0 )
  208. {
  209. /*
  210. * Northern hemisphere ordering
  211. */
  212. if ( CompareSYSTEMTIME(pst, &tzTime.DaylightDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.StandardDate) > 0)
  213. {
  214. lRes = tzTime.Bias * -1;
  215. }
  216. else
  217. {
  218. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  219. }
  220. }
  221. else
  222. {
  223. /*
  224. * Southern hemisphere ordering
  225. */
  226. if ( CompareSYSTEMTIME(pst, &tzTime.StandardDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.DaylightDate) > 0)
  227. {
  228. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  229. }
  230. else
  231. {
  232. lRes = tzTime.Bias * -1;
  233. }
  234. }
  235. break;
  236. }
  237. case TIME_ZONE_ID_INVALID:
  238. default:
  239. {
  240. // Can't read the timezone info
  241. ASSERT_BREAK(BAD_TIMEZONE);
  242. break;
  243. }
  244. }
  245. return lRes;
  246. }
  247. ///////////////////////////////////////////////////////////////////////////
  248. // WBEMTime - This class holds time values.
  249. //***************************************************************************
  250. //
  251. // WBEMTime::operator=(BSTR bstrWbemFormat)
  252. //
  253. // Description: Assignment operator which is also used by the constructor.
  254. // The string must have the format:
  255. // YYYYMMDDHHSS.123456789 So 3:04 am, 1/1/96 would be 199601010304.0
  256. //
  257. // or the format yyyymmddhhmmss.mmmmmmsuuu.
  258. //
  259. // Note that the fractional part can be between 1 and nine digits.
  260. //
  261. // Return: WBEMTime object.
  262. //
  263. //***************************************************************************
  264. const WBEMTime & WBEMTime::operator=(const BSTR bstrWbemFormat)
  265. {
  266. Clear(); // set when properly assigned
  267. if((NULL == bstrWbemFormat) ||
  268. bstrWbemFormat[DECPOS] != L'.'
  269. )
  270. {
  271. ASSERT_BREAK(INVALID_TIME_FORMAT);
  272. return *this;
  273. }
  274. if ( (wcslen(bstrWbemFormat) == DMTFLEN) &&
  275. (bstrWbemFormat[SGNPOS] == L'+' || bstrWbemFormat[SGNPOS] == L'-') )
  276. {
  277. SetDMTF(bstrWbemFormat);
  278. }
  279. else
  280. {
  281. ASSERT_BREAK(INVALID_TIME_FORMAT);
  282. }
  283. return *this;
  284. }
  285. //***************************************************************************
  286. //
  287. // WBEMTime::operator=(const SYSTEMTIME)
  288. //
  289. // Description: Assignment operator which is also used by the constructor.
  290. // This takes a standard WIN32 SYSTEMTIME stucture.
  291. //
  292. // Return: WBEMTime object.
  293. //
  294. //***************************************************************************
  295. const WBEMTime & WBEMTime::operator=(const SYSTEMTIME & st)
  296. {
  297. Clear(); // set when properly assigned
  298. FILETIME t_ft;
  299. if ( SystemTimeToFileTime(&st, &t_ft) )
  300. {
  301. // now assign using a FILETIME.
  302. *this = t_ft;
  303. }
  304. else
  305. {
  306. ASSERT_BREAK(INVALID_TIME_FORMAT);
  307. }
  308. return *this;
  309. }
  310. //***************************************************************************
  311. //
  312. // WBEMTime::operator=(const FILETIME)
  313. //
  314. // Description: Assignment operator which is also used by the constructor.
  315. // This takes a standard WIN32 FILETIME stucture.
  316. //
  317. // Return: WBEMTime object.
  318. //
  319. //***************************************************************************
  320. const WBEMTime & WBEMTime::operator=(const FILETIME & ft)
  321. {
  322. FileTimeToui64(&ft, &m_uTime);
  323. return *this;
  324. }
  325. //***************************************************************************
  326. //
  327. // WBEMTime::operator=(struct tm tmin)
  328. //
  329. // Description: Assignment operator which is also used by the constructor.
  330. // This takes a standard c runtine struct tm stucture.
  331. //
  332. // Return: WBEMTime object.
  333. //
  334. //***************************************************************************
  335. const WBEMTime & WBEMTime::operator=(const struct tm &a_tmin)
  336. {
  337. Clear(); // set when properly assigned
  338. SYSTEMTIME systemTime;
  339. if (StructtmToSystemTime(&a_tmin, &systemTime))
  340. {
  341. *this = systemTime;
  342. }
  343. return *this;
  344. }
  345. //***************************************************************************
  346. //
  347. // WBEMTime::operator=(struct time_t t)
  348. //
  349. // Description: Assignment operator which is also used by the constructor.
  350. // This takes a standard c runtine time_t stucture.
  351. //
  352. // Return: WBEMTime object.
  353. //
  354. //***************************************************************************
  355. const WBEMTime & WBEMTime::operator=(const time_t & t)
  356. {
  357. if (t >= 0)
  358. {
  359. m_uTime = Int32x32To64(t, 10000000) + 116444736000000000;
  360. }
  361. else
  362. {
  363. Clear();
  364. }
  365. return *this;
  366. }
  367. //***************************************************************************
  368. //
  369. // WBEMTime::operator+(const WBEMTime &uAdd)
  370. //
  371. // Description: dummy function for adding two WBEMTime. It doesnt really
  372. // make sense to add two date, but this is here for Tomas's template.
  373. //
  374. // Return: WBEMTime object.
  375. //
  376. //***************************************************************************
  377. WBEMTime WBEMTime::operator+(const WBEMTimeSpan &uAdd) const
  378. {
  379. WBEMTime ret;
  380. if (IsOk() && uAdd.IsOk())
  381. {
  382. ret.m_uTime = m_uTime + uAdd.m_Time;
  383. }
  384. else
  385. {
  386. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  387. }
  388. return ret;
  389. }
  390. const WBEMTime &WBEMTime::operator+=( const WBEMTimeSpan &ts )
  391. {
  392. if (IsOk() && ts.IsOk())
  393. {
  394. m_uTime += ts.m_Time ;
  395. }
  396. else
  397. {
  398. Clear();
  399. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  400. }
  401. return *this ;
  402. }
  403. //***************************************************************************
  404. //
  405. // WBEMTime::operator-(const WBEMTime & sub)
  406. //
  407. // Description: returns a WBEMTimeSpan object as the difference between
  408. // two WBEMTime objects.
  409. //
  410. // Return: WBEMTimeSpan object.
  411. //
  412. //***************************************************************************
  413. WBEMTimeSpan WBEMTime::operator-(const WBEMTime & sub)
  414. {
  415. WBEMTimeSpan ret;
  416. if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_uTime))
  417. {
  418. ret.m_Time = m_uTime-sub.m_uTime;
  419. }
  420. else
  421. {
  422. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  423. }
  424. return ret;
  425. }
  426. WBEMTime WBEMTime::operator-(const WBEMTimeSpan & sub) const
  427. {
  428. WBEMTime ret;
  429. if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_Time))
  430. {
  431. ret.m_uTime = m_uTime - sub.m_Time;
  432. }
  433. else
  434. {
  435. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  436. }
  437. return ret;
  438. }
  439. const WBEMTime &WBEMTime::operator-=(const WBEMTimeSpan & sub)
  440. {
  441. if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_Time))
  442. {
  443. m_uTime -= sub.m_Time;
  444. }
  445. else
  446. {
  447. Clear();
  448. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  449. }
  450. return *this;
  451. }
  452. //***************************************************************************
  453. //
  454. // WBEMTime::GetBSTR(void)
  455. //
  456. // This function used to CLAIM to do this:
  457. //
  458. // WRONG Description: Converts the time which is stored as the number of
  459. // nano seconds since 1970 into a bstr with this format.
  460. // YYYYMMDDHHSS.123456789 So 3:04 am, 1/1/96 would be 199601010304.000000000
  461. //
  462. // What it really did was return some bastardized form of a dmtf string. Now
  463. // it returns a dmtf string in gmt form (which is what the docs claim).
  464. //
  465. // Return: BSTR representation of time, or NULL if error. Note that the
  466. // caller should free up this string!
  467. //
  468. //***************************************************************************
  469. BSTR WBEMTime::GetBSTR(void) const
  470. {
  471. return GetDMTF(false) ;
  472. }
  473. //***************************************************************************
  474. //
  475. // WBEMTime::GetDMTFNonNtfs(void)
  476. //
  477. //***************************************************************************
  478. BSTR WBEMTime::GetDMTFNonNtfs(void) const
  479. {
  480. FILETIME t_ft1, t_ft2;
  481. BSTR t_Date = NULL;
  482. if (GetFILETIME(&t_ft1) && FileTimeToLocalFileTime(&t_ft1, &t_ft2))
  483. {
  484. t_Date = WBEMTime(t_ft2).GetDMTF();
  485. if (t_Date != NULL)
  486. {
  487. t_Date[21] = L'+';
  488. t_Date[22] = L'*';
  489. t_Date[23] = L'*';
  490. t_Date[24] = L'*';
  491. }
  492. }
  493. return t_Date;
  494. }
  495. //***************************************************************************
  496. //
  497. // WBEMTime::time_t(time_t * ptm)
  498. //
  499. // Return: TRUE if OK.
  500. //
  501. //***************************************************************************
  502. BOOL WBEMTime::Gettime_t(time_t * ptm) const
  503. {
  504. if( (!IsOk()) || (ptm == NULL) || (*this < g_Jan1970))
  505. {
  506. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  507. return FALSE;
  508. }
  509. if (g_Jan1970 != *this)
  510. {
  511. LONGLONG t_tmp = ( (m_uTime - g_Jan1970.m_uTime) / 10000000);
  512. if (t_tmp <= (LONGLONG)0xffffffff)
  513. {
  514. *ptm = (time_t)t_tmp;
  515. }
  516. else
  517. {
  518. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  519. return FALSE;
  520. }
  521. }
  522. else
  523. {
  524. *ptm = 0;
  525. }
  526. return TRUE;
  527. }
  528. //***************************************************************************
  529. //
  530. // WBEMTime::GetStructtm(struct tm * ptm)
  531. //
  532. // Return: TRUE if OK.
  533. //
  534. //***************************************************************************
  535. BOOL WBEMTime::GetStructtm(struct tm * ptm) const
  536. {
  537. SYSTEMTIME systemTime;
  538. return (GetSYSTEMTIME(&systemTime) && SystemTimeToStructtm(&systemTime, ptm));
  539. }
  540. //***************************************************************************
  541. //
  542. // WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst)
  543. //
  544. // Return: TRUE if OK.
  545. //
  546. //***************************************************************************
  547. BOOL WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst) const
  548. {
  549. if ((pst == NULL) || (!IsOk()))
  550. {
  551. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  552. return FALSE;
  553. }
  554. FILETIME t_ft;
  555. if (GetFILETIME(&t_ft))
  556. {
  557. if (!FileTimeToSystemTime(&t_ft, pst))
  558. {
  559. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  560. return FALSE;
  561. }
  562. }
  563. else
  564. {
  565. return FALSE;
  566. }
  567. return TRUE;
  568. }
  569. //***************************************************************************
  570. //
  571. // WBEMTime::GetFILETIME(FILETIME * pst)
  572. //
  573. // Return: TRUE if OK.
  574. //
  575. //***************************************************************************
  576. BOOL WBEMTime::GetFILETIME(FILETIME * pft) const
  577. {
  578. if ((pft == NULL) || (!IsOk()))
  579. {
  580. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  581. return FALSE;
  582. }
  583. ui64ToFileTime(&m_uTime, pft);
  584. return TRUE;
  585. }
  586. //***************************************************************************
  587. //
  588. // CWbemTime::SetDMTF(BSTR wszText)
  589. //
  590. // Description: Sets the time value to the DMTF string datetime value
  591. // passed as the parameter
  592. //
  593. // Return: TRUE if OK.
  594. //
  595. //***************************************************************************
  596. BOOL WBEMTime::SetDMTF( const BSTR a_wszText )
  597. {
  598. wchar_t t_DefaultBuffer[] = {L"16010101000000.000000+000"} ;
  599. wchar_t t_DateBuffer[ DMTFLEN + 1 ] ;
  600. t_DateBuffer[ DMTFLEN ] = NULL ;
  601. bstr_t t_bstrDate( a_wszText ) ;
  602. // wildcard cleanup and validation
  603. // ===============================
  604. if( DMTFLEN != t_bstrDate.length() )
  605. {
  606. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  607. return FALSE ;
  608. }
  609. wchar_t *t_pwBuffer = (wchar_t*)t_bstrDate ;
  610. for( int t_i = 0; t_i < DMTFLEN; t_i++ )
  611. {
  612. switch( t_pwBuffer[ t_i ] )
  613. {
  614. case '0':
  615. case '1':
  616. case '2':
  617. case '3':
  618. case '4':
  619. case '5':
  620. case '6':
  621. case '7':
  622. case '8':
  623. case '9':
  624. {
  625. // stepping on separator or sign
  626. if( DECPOS == t_i || SGNPOS == t_i )
  627. {
  628. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  629. return FALSE ;
  630. }
  631. t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
  632. break ;
  633. }
  634. case '*':
  635. {
  636. // stepping on separator or sign
  637. if( DECPOS == t_i || SGNPOS == t_i )
  638. {
  639. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  640. return FALSE ;
  641. }
  642. else
  643. {
  644. // replace with default stamp
  645. t_DateBuffer[ t_i ] = t_DefaultBuffer[ t_i ] ;
  646. }
  647. break ;
  648. }
  649. case '.':
  650. {
  651. if( DECPOS != t_i )
  652. {
  653. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  654. return FALSE ;
  655. }
  656. t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
  657. break ;
  658. }
  659. case '+':
  660. case '-':
  661. {
  662. if( SGNPOS != t_i )
  663. {
  664. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  665. return FALSE ;
  666. }
  667. t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
  668. break ;
  669. }
  670. default:
  671. {
  672. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  673. return FALSE ;
  674. }
  675. }
  676. }
  677. // Parse it
  678. // ========
  679. int nYear, nMonth, nDay, nHour, nMinute, nSecond, nMicro, nOffset;
  680. WCHAR wchSep;
  681. int nRes = swscanf (
  682. (LPCWSTR)&t_DateBuffer,
  683. L"%4d%2d%2d%2d%2d%2d.%6d%c%3d",
  684. &nYear,
  685. &nMonth,
  686. &nDay,
  687. &nHour,
  688. &nMinute,
  689. &nSecond,
  690. &nMicro,
  691. &wchSep,
  692. &nOffset
  693. );
  694. if ( ( 9 != nRes ) || ( 1601 > nYear) )
  695. {
  696. ASSERT_BREAK(INVALID_TIME_FORMAT);
  697. return FALSE;
  698. }
  699. // Convert it to SYSTEMTIME
  700. // ========================
  701. SYSTEMTIME st;
  702. st.wYear = (WORD)nYear;
  703. st.wMonth = (WORD)nMonth;
  704. st.wDay = (WORD)nDay;
  705. st.wHour = (WORD)nHour;
  706. st.wMinute = (WORD)nMinute;
  707. st.wSecond = (WORD)nSecond;
  708. st.wMilliseconds = nMicro / 1000;
  709. st.wDayOfWeek = 0;
  710. *this = st;
  711. // NOW we adjust for the offset
  712. // ============================
  713. if ( IsOk() )
  714. {
  715. int nSign = (wchSep == L'+') ? 1 : -1 ;
  716. m_uTime -= (LONGLONG)nSign * (LONGLONG)nOffset * 60 * 10000000;
  717. }
  718. else
  719. {
  720. ASSERT_BREAK( INVALID_TIME_ARITHMETIC ) ;
  721. return FALSE ;
  722. }
  723. return TRUE;
  724. }
  725. //***************************************************************************
  726. //
  727. // BSTR WBEMTime::GetDMTF(void)
  728. //
  729. // Description: Gets the time in DMTF string datetime format. User must call
  730. // SysFreeString with the result. If bLocal is true, then the time is given
  731. // in the local timezone, else the time is given in GMT.
  732. //
  733. // Return: NULL if not OK.
  734. //
  735. //***************************************************************************
  736. BSTR WBEMTime::GetDMTF(BOOL bLocal) const
  737. {
  738. if (!IsOk())
  739. {
  740. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  741. return NULL;
  742. }
  743. SYSTEMTIME t_Systime;
  744. wchar_t chsign = L'-';
  745. int offset = 0;
  746. // If the date to be converted is within 12 hours of
  747. // 1/1/1601, return the greenwich time
  748. ULONGLONG t_ConversionZone = 12L * 60L * 60L ;
  749. t_ConversionZone = t_ConversionZone * 10000000L ;
  750. if ( !bLocal || ( m_uTime < t_ConversionZone ) )
  751. {
  752. if(!GetSYSTEMTIME(&t_Systime))
  753. {
  754. return NULL;
  755. }
  756. }
  757. else
  758. {
  759. if (GetSYSTEMTIME(&t_Systime))
  760. {
  761. offset = GetLocalOffsetForDate(&t_Systime);
  762. WBEMTime wt;
  763. if (offset >= 0)
  764. {
  765. chsign = '+';
  766. wt = *this + WBEMTimeSpan(0, 0, offset, 0);
  767. }
  768. else
  769. {
  770. offset *= -1;
  771. wt = *this - WBEMTimeSpan(0, 0, offset, 0);
  772. }
  773. wt.GetSYSTEMTIME(&t_Systime);
  774. }
  775. else
  776. {
  777. return NULL;
  778. }
  779. }
  780. LONGLONG tmpMicros = m_uTime%10000000;
  781. LONG micros = (LONG)(tmpMicros / 10);
  782. BSTR t_String = SysAllocStringLen(NULL, DMTFLEN + 1);
  783. if ( ! t_String )
  784. {
  785. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  786. }
  787. swprintf(
  788. t_String,
  789. L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d%c%03.3ld",
  790. t_Systime.wYear,
  791. t_Systime.wMonth,
  792. t_Systime.wDay,
  793. t_Systime.wHour,
  794. t_Systime.wMinute,
  795. t_Systime.wSecond,
  796. micros,
  797. chsign,
  798. offset
  799. );
  800. return t_String ;
  801. }
  802. ///////////////////////////////////////////////////////////////////////////
  803. // WBEMTimeSpan - This class holds timespan values. The data is stored
  804. // in 100 nanosecond units (like FILETIME).
  805. //***************************************************************************
  806. //
  807. // WBEMTimeSpan::WBEMTimeSpan(int iDays, int iHours, int iMinutes, int iSeconds,
  808. // int iMSec, int iUSec, int iNSec)
  809. //
  810. // Description: Constructor.
  811. //
  812. //***************************************************************************
  813. WBEMTimeSpan::WBEMTimeSpan(int iDays, int iHours, int iMinutes, int iSeconds,
  814. int iMSec, int iUSec, int iNSec)
  815. {
  816. m_Time = 0; //todo, check values!!!
  817. m_Time += iSeconds;
  818. m_Time += iMinutes * 60;
  819. m_Time += iHours * 60 * 60;
  820. m_Time += iDays * 24 * 60 * 60;
  821. m_Time *= 10000000;
  822. m_Time += iNSec / 100; // Nanoseconds
  823. m_Time += iUSec*10; // Microseconds
  824. m_Time += iMSec*10000; // Milliseconds
  825. }
  826. WBEMTimeSpan::WBEMTimeSpan ( const FILETIME &ft )
  827. {
  828. ASSERT_BREAK(DEPRECATED);
  829. *this = ft ;
  830. }
  831. WBEMTimeSpan::WBEMTimeSpan ( const time_t & t )
  832. {
  833. ASSERT_BREAK(DEPRECATED);
  834. *this = t ;
  835. } ;
  836. //***************************************************************************
  837. //
  838. // WBEMTimeSpan::operator=(const BSTR bstrWbemFormat)
  839. //
  840. // Return: WBEMTimeSpan object.
  841. //
  842. //***************************************************************************
  843. const WBEMTimeSpan & WBEMTimeSpan::operator=(const BSTR bstrWbemFormat)
  844. {
  845. Clear();
  846. // all characters should be digits except for one which
  847. // must be a period
  848. if ((bstrWbemFormat == NULL) || (bstrWbemFormat[DECPOS] != L'.') ||
  849. (wcslen(bstrWbemFormat) != DMTFLEN) || (bstrWbemFormat[SGNPOS] != L':') )
  850. {
  851. ASSERT_BREAK(INVALID_TIME_FORMAT);
  852. return *this;
  853. }
  854. int nDays, nHours, nMinutes, nSeconds, nMicros, nOffset;
  855. WCHAR wchSep;
  856. int nRes = swscanf (
  857. bstrWbemFormat,
  858. L"%8d%2d%2d%2d.%6d%c%3d",
  859. &nDays,
  860. &nHours,
  861. &nMinutes,
  862. &nSeconds,
  863. &nMicros,
  864. &wchSep,
  865. &nOffset
  866. );
  867. if ( (nRes != 7) || ( nOffset != 0) )
  868. {
  869. ASSERT_BREAK(INVALID_TIME_FORMAT);
  870. return *this;
  871. }
  872. *this = WBEMTimeSpan(nDays, nHours, nMinutes, nSeconds, 0, nMicros, 0);
  873. return *this;
  874. }
  875. //***************************************************************************
  876. //
  877. // WBEMTimeSpan::operator=(const FILETIME &)
  878. // WBEMTimeSpan::operator=(const time_t &)
  879. //
  880. // Description: Assignment operator which is also used by the constructor.
  881. //
  882. // Return: WBEMTimeSpan object.
  883. //
  884. //***************************************************************************
  885. const WBEMTimeSpan & WBEMTimeSpan::operator=(const FILETIME &ft)
  886. {
  887. ASSERT_BREAK(DEPRECATED);
  888. ULONGLONG uTemp;
  889. FileTimeToui64(&ft, &uTemp);
  890. m_Time = uTemp;
  891. return *this;
  892. }
  893. const WBEMTimeSpan & WBEMTimeSpan::operator=(const time_t & t)
  894. {
  895. ASSERT_BREAK(DEPRECATED);
  896. ULONGLONG uTemp = 0;
  897. uTemp = t;
  898. if (t >= 0)
  899. {
  900. m_Time = uTemp * 10000000;
  901. }
  902. else
  903. {
  904. Clear();
  905. }
  906. return *this;
  907. }
  908. //***************************************************************************
  909. //
  910. // WBEMTimeSpan::operator +(const WBEMTimeSpan &uAdd)
  911. //
  912. // Description: function for adding two WBEMTimeSpan objects.
  913. //
  914. // Return: WBEMTimeSpan object.
  915. //
  916. //***************************************************************************
  917. WBEMTimeSpan WBEMTimeSpan::operator+(const WBEMTimeSpan &uAdd) const
  918. {
  919. WBEMTimeSpan ret;
  920. if (IsOk() && uAdd.IsOk())
  921. {
  922. ret.m_Time = m_Time + uAdd.m_Time;
  923. }
  924. else
  925. {
  926. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  927. }
  928. return ret;
  929. }
  930. const WBEMTimeSpan &WBEMTimeSpan::operator+= ( const WBEMTimeSpan &uAdd )
  931. {
  932. if (IsOk() && uAdd.IsOk())
  933. {
  934. m_Time += uAdd.m_Time ;
  935. }
  936. else
  937. {
  938. Clear();
  939. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  940. }
  941. return *this ;
  942. }
  943. //***************************************************************************
  944. //
  945. // WBEMTimeSpan::operator -(const WBEMTimeSpan &uAdd)
  946. //
  947. // Description: function for adding two WBEMTimeSpan objects.
  948. //
  949. // Return: WBEMTimeSpan object.
  950. //
  951. //***************************************************************************
  952. WBEMTimeSpan WBEMTimeSpan::operator-(const WBEMTimeSpan &uSub) const
  953. {
  954. WBEMTimeSpan ret;
  955. if (IsOk() && uSub.IsOk() && (m_Time >= uSub.m_Time))
  956. {
  957. ret.m_Time = m_Time - uSub.m_Time;
  958. }
  959. else
  960. {
  961. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  962. }
  963. return ret;
  964. }
  965. const WBEMTimeSpan &WBEMTimeSpan::operator-= ( const WBEMTimeSpan &uSub )
  966. {
  967. if (IsOk() && uSub.IsOk() && (m_Time >= uSub.m_Time))
  968. {
  969. m_Time -= uSub.m_Time;
  970. }
  971. else
  972. {
  973. Clear();
  974. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  975. }
  976. return *this;
  977. }
  978. //***************************************************************************
  979. //
  980. // WBEMTimeSpan::GetBSTR(void)
  981. //
  982. // Description: Converts the time which is stored as the number of
  983. // 100 nano second units into a dmtf formatted string
  984. // ddddddddhhmmss.mmmmmm:000
  985. //
  986. // Return: BSTR representation of time, or NULL if error. Note that the
  987. // caller should free up this string!
  988. //
  989. //***************************************************************************
  990. BSTR WBEMTimeSpan::GetBSTR(void) const
  991. {
  992. if(!IsOk())
  993. {
  994. return NULL;
  995. }
  996. ULONGLONG Time = m_Time;
  997. // The /10 is to convert from 100ns to microseconds
  998. long iMicro = (long)((Time % 10000000) / 10);
  999. Time /= 10000000;
  1000. int iSec = (int)(Time % 60);
  1001. Time /= 60;
  1002. int iMin = (int)(Time % 60);
  1003. Time /= 60;
  1004. int iHour = (int)(Time % 24);
  1005. Time /= 24;
  1006. BSTR t_String = SysAllocStringLen(NULL, DMTFLEN + 1);
  1007. if ( ! t_String )
  1008. {
  1009. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1010. }
  1011. swprintf(t_String, L"%08I64i%02d%02d%02d.%06ld:000",
  1012. Time, iHour, iMin, iSec, iMicro);
  1013. return t_String ;
  1014. }
  1015. //***************************************************************************
  1016. //
  1017. // WBEMTimeSpan::Gettime_t(void)
  1018. // WBEMTimeSpan::GetFILETIME(void)
  1019. //
  1020. // Description: Converts the time span which is stored as the number of
  1021. // nano seconds into common stuctures.
  1022. //
  1023. // Return: TRUE if OK.
  1024. //
  1025. //***************************************************************************
  1026. BOOL WBEMTimeSpan::Gettime_t(time_t * ptime_t) const
  1027. {
  1028. ASSERT_BREAK(DEPRECATED);
  1029. if(!IsOk())
  1030. {
  1031. return FALSE;
  1032. }
  1033. *ptime_t = (DWORD)(m_Time / 10000000);
  1034. return TRUE;
  1035. }
  1036. BOOL WBEMTimeSpan::GetFILETIME(FILETIME * pst) const
  1037. {
  1038. ASSERT_BREAK(DEPRECATED);
  1039. if(!IsOk())
  1040. {
  1041. return FALSE;
  1042. }
  1043. ULONGLONG uTemp;
  1044. uTemp = m_Time;
  1045. ui64ToFileTime(&uTemp,pst);
  1046. return TRUE;
  1047. }