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.

1244 lines
32 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright � 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. wcslen(bstrWbemFormat) != DMTFLEN ||
  269. bstrWbemFormat[DECPOS] != L'.'
  270. )
  271. {
  272. ASSERT_BREAK(INVALID_TIME_FORMAT);
  273. return *this;
  274. }
  275. if ( (wcslen(bstrWbemFormat) == DMTFLEN) &&
  276. (bstrWbemFormat[SGNPOS] == L'+' || bstrWbemFormat[SGNPOS] == L'-') )
  277. {
  278. SetDMTF(bstrWbemFormat);
  279. }
  280. else
  281. {
  282. ASSERT_BREAK(INVALID_TIME_FORMAT);
  283. }
  284. return *this;
  285. }
  286. //***************************************************************************
  287. //
  288. // WBEMTime::operator=(const SYSTEMTIME)
  289. //
  290. // Description: Assignment operator which is also used by the constructor.
  291. // This takes a standard WIN32 SYSTEMTIME stucture.
  292. //
  293. // Return: WBEMTime object.
  294. //
  295. //***************************************************************************
  296. const WBEMTime & WBEMTime::operator=(const SYSTEMTIME & st)
  297. {
  298. Clear(); // set when properly assigned
  299. FILETIME t_ft;
  300. if ( SystemTimeToFileTime(&st, &t_ft) )
  301. {
  302. // now assign using a FILETIME.
  303. *this = t_ft;
  304. }
  305. else
  306. {
  307. ASSERT_BREAK(INVALID_TIME_FORMAT);
  308. }
  309. return *this;
  310. }
  311. //***************************************************************************
  312. //
  313. // WBEMTime::operator=(const FILETIME)
  314. //
  315. // Description: Assignment operator which is also used by the constructor.
  316. // This takes a standard WIN32 FILETIME stucture.
  317. //
  318. // Return: WBEMTime object.
  319. //
  320. //***************************************************************************
  321. const WBEMTime & WBEMTime::operator=(const FILETIME & ft)
  322. {
  323. FileTimeToui64(&ft, &m_uTime);
  324. return *this;
  325. }
  326. //***************************************************************************
  327. //
  328. // WBEMTime::operator=(struct tm tmin)
  329. //
  330. // Description: Assignment operator which is also used by the constructor.
  331. // This takes a standard c runtine struct tm stucture.
  332. //
  333. // Return: WBEMTime object.
  334. //
  335. //***************************************************************************
  336. const WBEMTime & WBEMTime::operator=(const struct tm &a_tmin)
  337. {
  338. Clear(); // set when properly assigned
  339. SYSTEMTIME systemTime;
  340. if (StructtmToSystemTime(&a_tmin, &systemTime))
  341. {
  342. *this = systemTime;
  343. }
  344. return *this;
  345. }
  346. //***************************************************************************
  347. //
  348. // WBEMTime::operator=(struct time_t t)
  349. //
  350. // Description: Assignment operator which is also used by the constructor.
  351. // This takes a standard c runtine time_t stucture.
  352. //
  353. // Return: WBEMTime object.
  354. //
  355. //***************************************************************************
  356. const WBEMTime & WBEMTime::operator=(const time_t & t)
  357. {
  358. if (t >= 0)
  359. {
  360. m_uTime = Int32x32To64(t, 10000000) + 116444736000000000;
  361. }
  362. else
  363. {
  364. Clear();
  365. }
  366. return *this;
  367. }
  368. //***************************************************************************
  369. //
  370. // WBEMTime::operator+(const WBEMTime &uAdd)
  371. //
  372. // Description: dummy function for adding two WBEMTime. It doesnt really
  373. // make sense to add two date, but this is here for Tomas's template.
  374. //
  375. // Return: WBEMTime object.
  376. //
  377. //***************************************************************************
  378. WBEMTime WBEMTime::operator+(const WBEMTimeSpan &uAdd) const
  379. {
  380. WBEMTime ret;
  381. if (IsOk() && uAdd.IsOk())
  382. {
  383. ret.m_uTime = m_uTime + uAdd.m_Time;
  384. }
  385. else
  386. {
  387. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  388. }
  389. return ret;
  390. }
  391. const WBEMTime &WBEMTime::operator+=( const WBEMTimeSpan &ts )
  392. {
  393. if (IsOk() && ts.IsOk())
  394. {
  395. m_uTime += ts.m_Time ;
  396. }
  397. else
  398. {
  399. Clear();
  400. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  401. }
  402. return *this ;
  403. }
  404. //***************************************************************************
  405. //
  406. // WBEMTime::operator-(const WBEMTime & sub)
  407. //
  408. // Description: returns a WBEMTimeSpan object as the difference between
  409. // two WBEMTime objects.
  410. //
  411. // Return: WBEMTimeSpan object.
  412. //
  413. //***************************************************************************
  414. WBEMTimeSpan WBEMTime::operator-(const WBEMTime & sub)
  415. {
  416. WBEMTimeSpan ret;
  417. if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_uTime))
  418. {
  419. ret.m_Time = m_uTime-sub.m_uTime;
  420. }
  421. else
  422. {
  423. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  424. }
  425. return ret;
  426. }
  427. WBEMTime WBEMTime::operator-(const WBEMTimeSpan & sub) const
  428. {
  429. WBEMTime ret;
  430. if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_Time))
  431. {
  432. ret.m_uTime = m_uTime - sub.m_Time;
  433. }
  434. else
  435. {
  436. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  437. }
  438. return ret;
  439. }
  440. const WBEMTime &WBEMTime::operator-=(const WBEMTimeSpan & sub)
  441. {
  442. if (IsOk() && sub.IsOk() && (m_uTime >= sub.m_Time))
  443. {
  444. m_uTime -= sub.m_Time;
  445. }
  446. else
  447. {
  448. Clear();
  449. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  450. }
  451. return *this;
  452. }
  453. //***************************************************************************
  454. //
  455. // WBEMTime::GetBSTR(void)
  456. //
  457. // This function used to CLAIM to do this:
  458. //
  459. // WRONG Description: Converts the time which is stored as the number of
  460. // nano seconds since 1970 into a bstr with this format.
  461. // YYYYMMDDHHSS.123456789 So 3:04 am, 1/1/96 would be 199601010304.000000000
  462. //
  463. // What it really did was return some bastardized form of a dmtf string. Now
  464. // it returns a dmtf string in gmt form (which is what the docs claim).
  465. //
  466. // Return: BSTR representation of time, or NULL if error. Note that the
  467. // caller should free up this string!
  468. //
  469. //***************************************************************************
  470. BSTR WBEMTime::GetBSTR(void) const
  471. {
  472. return GetDMTF(false) ;
  473. }
  474. //***************************************************************************
  475. //
  476. // WBEMTime::GetDMTFNonNtfs(void)
  477. //
  478. //***************************************************************************
  479. BSTR WBEMTime::GetDMTFNonNtfs(void) const
  480. {
  481. FILETIME t_ft1, t_ft2;
  482. BSTR t_Date = NULL;
  483. if (GetFILETIME(&t_ft1) && FileTimeToLocalFileTime(&t_ft1, &t_ft2))
  484. {
  485. t_Date = WBEMTime(t_ft2).GetDMTF();
  486. if (t_Date != NULL)
  487. {
  488. t_Date[21] = L'+';
  489. t_Date[22] = L'*';
  490. t_Date[23] = L'*';
  491. t_Date[24] = L'*';
  492. }
  493. }
  494. return t_Date;
  495. }
  496. //***************************************************************************
  497. //
  498. // WBEMTime::time_t(time_t * ptm)
  499. //
  500. // Return: TRUE if OK.
  501. //
  502. //***************************************************************************
  503. BOOL WBEMTime::Gettime_t(time_t * ptm) const
  504. {
  505. if( (!IsOk()) || (ptm == NULL) || (*this < g_Jan1970))
  506. {
  507. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  508. return FALSE;
  509. }
  510. if (g_Jan1970 != *this)
  511. {
  512. LONGLONG t_tmp = ( (m_uTime - g_Jan1970.m_uTime) / 10000000);
  513. if (t_tmp <= (LONGLONG)0xffffffff)
  514. {
  515. *ptm = (time_t)t_tmp;
  516. }
  517. else
  518. {
  519. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  520. return FALSE;
  521. }
  522. }
  523. else
  524. {
  525. *ptm = 0;
  526. }
  527. return TRUE;
  528. }
  529. //***************************************************************************
  530. //
  531. // WBEMTime::GetStructtm(struct tm * ptm)
  532. //
  533. // Return: TRUE if OK.
  534. //
  535. //***************************************************************************
  536. BOOL WBEMTime::GetStructtm(struct tm * ptm) const
  537. {
  538. SYSTEMTIME systemTime;
  539. return (GetSYSTEMTIME(&systemTime) && SystemTimeToStructtm(&systemTime, ptm));
  540. }
  541. //***************************************************************************
  542. //
  543. // WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst)
  544. //
  545. // Return: TRUE if OK.
  546. //
  547. //***************************************************************************
  548. BOOL WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst) const
  549. {
  550. if ((pst == NULL) || (!IsOk()))
  551. {
  552. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  553. return FALSE;
  554. }
  555. FILETIME t_ft;
  556. if (GetFILETIME(&t_ft))
  557. {
  558. if (!FileTimeToSystemTime(&t_ft, pst))
  559. {
  560. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  561. return FALSE;
  562. }
  563. }
  564. else
  565. {
  566. return FALSE;
  567. }
  568. return TRUE;
  569. }
  570. //***************************************************************************
  571. //
  572. // WBEMTime::GetFILETIME(FILETIME * pst)
  573. //
  574. // Return: TRUE if OK.
  575. //
  576. //***************************************************************************
  577. BOOL WBEMTime::GetFILETIME(FILETIME * pft) const
  578. {
  579. if ((pft == NULL) || (!IsOk()))
  580. {
  581. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  582. return FALSE;
  583. }
  584. ui64ToFileTime(&m_uTime, pft);
  585. return TRUE;
  586. }
  587. //***************************************************************************
  588. //
  589. // CWbemTime::SetDMTF(BSTR wszText)
  590. //
  591. // Description: Sets the time value to the DMTF string datetime value
  592. // passed as the parameter
  593. //
  594. // Return: TRUE if OK.
  595. //
  596. //***************************************************************************
  597. BOOL WBEMTime::SetDMTF( const BSTR a_wszText )
  598. {
  599. wchar_t t_DefaultBuffer[] = {L"16010101000000.000000+000"} ;
  600. wchar_t t_DateBuffer[ DMTFLEN + 1 ] ;
  601. t_DateBuffer[ DMTFLEN ] = NULL ;
  602. bstr_t t_bstrDate( a_wszText ) ;
  603. // wildcard cleanup and validation
  604. // ===============================
  605. if( DMTFLEN != t_bstrDate.length() )
  606. {
  607. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  608. return FALSE ;
  609. }
  610. wchar_t *t_pwBuffer = (wchar_t*)t_bstrDate ;
  611. for( int t_i = 0; t_i < DMTFLEN; t_i++ )
  612. {
  613. switch( t_pwBuffer[ t_i ] )
  614. {
  615. case '0':
  616. case '1':
  617. case '2':
  618. case '3':
  619. case '4':
  620. case '5':
  621. case '6':
  622. case '7':
  623. case '8':
  624. case '9':
  625. {
  626. // stepping on separator or sign
  627. if( DECPOS == t_i || SGNPOS == t_i )
  628. {
  629. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  630. return FALSE ;
  631. }
  632. t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
  633. break ;
  634. }
  635. case '*':
  636. {
  637. // stepping on separator or sign
  638. if( DECPOS == t_i || SGNPOS == t_i )
  639. {
  640. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  641. return FALSE ;
  642. }
  643. else
  644. {
  645. // replace with default stamp
  646. t_DateBuffer[ t_i ] = t_DefaultBuffer[ t_i ] ;
  647. }
  648. break ;
  649. }
  650. case '.':
  651. {
  652. if( DECPOS != t_i )
  653. {
  654. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  655. return FALSE ;
  656. }
  657. t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
  658. break ;
  659. }
  660. case '+':
  661. case '-':
  662. {
  663. if( SGNPOS != t_i )
  664. {
  665. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  666. return FALSE ;
  667. }
  668. t_DateBuffer[ t_i ] = t_pwBuffer[ t_i ] ;
  669. break ;
  670. }
  671. default:
  672. {
  673. ASSERT_BREAK( INVALID_TIME_FORMAT ) ;
  674. return FALSE ;
  675. }
  676. }
  677. }
  678. // Parse it
  679. // ========
  680. int nYear, nMonth, nDay, nHour, nMinute, nSecond, nMicro, nOffset;
  681. WCHAR wchSep;
  682. int nRes = swscanf (
  683. (LPCWSTR)&t_DateBuffer,
  684. L"%4d%2d%2d%2d%2d%2d.%6d%c%3d",
  685. &nYear,
  686. &nMonth,
  687. &nDay,
  688. &nHour,
  689. &nMinute,
  690. &nSecond,
  691. &nMicro,
  692. &wchSep,
  693. &nOffset
  694. );
  695. if ( ( 9 != nRes ) || ( 1601 > nYear) )
  696. {
  697. ASSERT_BREAK(INVALID_TIME_FORMAT);
  698. return FALSE;
  699. }
  700. // Convert it to SYSTEMTIME
  701. // ========================
  702. SYSTEMTIME st;
  703. st.wYear = (WORD)nYear;
  704. st.wMonth = (WORD)nMonth;
  705. st.wDay = (WORD)nDay;
  706. st.wHour = (WORD)nHour;
  707. st.wMinute = (WORD)nMinute;
  708. st.wSecond = (WORD)nSecond;
  709. st.wMilliseconds = 0;
  710. st.wDayOfWeek = 0;
  711. *this = st;
  712. // we need to add microseconds and nanoseconds now!
  713. // it was basically cut when assigned to SYSTEMTIME
  714. // ================================================
  715. m_uTime += (LONGLONG)nMicro * 10;
  716. // NOW we adjust for the offset
  717. // ============================
  718. if ( IsOk() )
  719. {
  720. int nSign = (wchSep == L'+') ? 1 : -1 ;
  721. m_uTime -= (LONGLONG)nSign * (LONGLONG)nOffset * 60 * 10000000;
  722. }
  723. else
  724. {
  725. ASSERT_BREAK( INVALID_TIME_ARITHMETIC ) ;
  726. return FALSE ;
  727. }
  728. return TRUE;
  729. }
  730. //***************************************************************************
  731. //
  732. // BSTR WBEMTime::GetDMTF(void)
  733. //
  734. // Description: Gets the time in DMTF string datetime format. User must call
  735. // SysFreeString with the result. If bLocal is true, then the time is given
  736. // in the local timezone, else the time is given in GMT.
  737. //
  738. // Return: NULL if not OK.
  739. //
  740. //***************************************************************************
  741. BSTR WBEMTime::GetDMTF(BOOL bLocal) const
  742. {
  743. if (!IsOk())
  744. {
  745. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  746. return NULL;
  747. }
  748. SYSTEMTIME t_Systime;
  749. wchar_t chsign = L'-';
  750. int offset = 0;
  751. // If the date to be converted is within 12 hours of
  752. // 1/1/1601, return the greenwich time
  753. ULONGLONG t_ConversionZone = 12L * 60L * 60L ;
  754. t_ConversionZone = t_ConversionZone * 10000000L ;
  755. if ( !bLocal || ( m_uTime < t_ConversionZone ) )
  756. {
  757. if(!GetSYSTEMTIME(&t_Systime))
  758. {
  759. return NULL;
  760. }
  761. }
  762. else
  763. {
  764. if (GetSYSTEMTIME(&t_Systime))
  765. {
  766. offset = GetLocalOffsetForDate(&t_Systime);
  767. WBEMTime wt;
  768. if (offset >= 0)
  769. {
  770. chsign = '+';
  771. wt = *this + WBEMTimeSpan(0, 0, offset, 0);
  772. }
  773. else
  774. {
  775. offset *= -1;
  776. wt = *this - WBEMTimeSpan(0, 0, offset, 0);
  777. }
  778. wt.GetSYSTEMTIME(&t_Systime);
  779. }
  780. else
  781. {
  782. return NULL;
  783. }
  784. }
  785. LONGLONG tmpMicros = m_uTime%10000000;
  786. LONG micros = (LONG)(tmpMicros / 10);
  787. BSTR t_String = SysAllocStringLen(NULL, DMTFLEN + 1);
  788. if ( ! t_String )
  789. {
  790. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  791. }
  792. swprintf(
  793. t_String,
  794. L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d%c%03.3ld",
  795. t_Systime.wYear,
  796. t_Systime.wMonth,
  797. t_Systime.wDay,
  798. t_Systime.wHour,
  799. t_Systime.wMinute,
  800. t_Systime.wSecond,
  801. micros,
  802. chsign,
  803. offset
  804. );
  805. return t_String ;
  806. }
  807. ///////////////////////////////////////////////////////////////////////////
  808. // WBEMTimeSpan - This class holds timespan values. The data is stored
  809. // in 100 nanosecond units (like FILETIME).
  810. //***************************************************************************
  811. //
  812. // WBEMTimeSpan::WBEMTimeSpan(int iDays, int iHours, int iMinutes, int iSeconds,
  813. // int iMSec, int iUSec, int iNSec)
  814. //
  815. // Description: Constructor.
  816. //
  817. //***************************************************************************
  818. WBEMTimeSpan::WBEMTimeSpan(int iDays, int iHours, int iMinutes, int iSeconds,
  819. int iMSec, int iUSec, int iNSec)
  820. {
  821. m_Time = 0; //todo, check values!!!
  822. m_Time += iSeconds;
  823. m_Time += iMinutes * 60;
  824. m_Time += iHours * 60 * 60;
  825. m_Time += iDays * 24 * 60 * 60;
  826. m_Time *= 10000000;
  827. m_Time += iNSec / 100; // Nanoseconds
  828. m_Time += iUSec*10; // Microseconds
  829. m_Time += iMSec*10000; // Milliseconds
  830. }
  831. WBEMTimeSpan::WBEMTimeSpan ( const FILETIME &ft )
  832. {
  833. ASSERT_BREAK(DEPRECATED);
  834. *this = ft ;
  835. }
  836. WBEMTimeSpan::WBEMTimeSpan ( const time_t & t )
  837. {
  838. ASSERT_BREAK(DEPRECATED);
  839. *this = t ;
  840. } ;
  841. //***************************************************************************
  842. //
  843. // WBEMTimeSpan::operator=(const BSTR bstrWbemFormat)
  844. //
  845. // Return: WBEMTimeSpan object.
  846. //
  847. //***************************************************************************
  848. const WBEMTimeSpan & WBEMTimeSpan::operator=(const BSTR bstrWbemFormat)
  849. {
  850. Clear();
  851. // all characters should be digits except for one which
  852. // must be a period
  853. if ((bstrWbemFormat == NULL) || (bstrWbemFormat[DECPOS] != L'.') ||
  854. (wcslen(bstrWbemFormat) != DMTFLEN) || (bstrWbemFormat[SGNPOS] != L':') )
  855. {
  856. ASSERT_BREAK(INVALID_TIME_FORMAT);
  857. return *this;
  858. }
  859. int nDays, nHours, nMinutes, nSeconds, nMicros, nOffset;
  860. WCHAR wchSep;
  861. int nRes = swscanf (
  862. bstrWbemFormat,
  863. L"%8d%2d%2d%2d.%6d%c%3d",
  864. &nDays,
  865. &nHours,
  866. &nMinutes,
  867. &nSeconds,
  868. &nMicros,
  869. &wchSep,
  870. &nOffset
  871. );
  872. if ( (nRes != 7) || ( nOffset != 0) )
  873. {
  874. ASSERT_BREAK(INVALID_TIME_FORMAT);
  875. return *this;
  876. }
  877. *this = WBEMTimeSpan(nDays, nHours, nMinutes, nSeconds, 0, nMicros, 0);
  878. return *this;
  879. }
  880. //***************************************************************************
  881. //
  882. // WBEMTimeSpan::operator=(const FILETIME &)
  883. // WBEMTimeSpan::operator=(const time_t &)
  884. //
  885. // Description: Assignment operator which is also used by the constructor.
  886. //
  887. // Return: WBEMTimeSpan object.
  888. //
  889. //***************************************************************************
  890. const WBEMTimeSpan & WBEMTimeSpan::operator=(const FILETIME &ft)
  891. {
  892. ASSERT_BREAK(DEPRECATED);
  893. ULONGLONG uTemp;
  894. FileTimeToui64(&ft, &uTemp);
  895. m_Time = uTemp;
  896. return *this;
  897. }
  898. const WBEMTimeSpan & WBEMTimeSpan::operator=(const time_t & t)
  899. {
  900. ASSERT_BREAK(DEPRECATED);
  901. ULONGLONG uTemp = 0;
  902. uTemp = t;
  903. if (t >= 0)
  904. {
  905. m_Time = uTemp * 10000000;
  906. }
  907. else
  908. {
  909. Clear();
  910. }
  911. return *this;
  912. }
  913. //***************************************************************************
  914. //
  915. // WBEMTimeSpan::operator +(const WBEMTimeSpan &uAdd)
  916. //
  917. // Description: function for adding two WBEMTimeSpan objects.
  918. //
  919. // Return: WBEMTimeSpan object.
  920. //
  921. //***************************************************************************
  922. WBEMTimeSpan WBEMTimeSpan::operator+(const WBEMTimeSpan &uAdd) const
  923. {
  924. WBEMTimeSpan ret;
  925. if (IsOk() && uAdd.IsOk())
  926. {
  927. ret.m_Time = m_Time + uAdd.m_Time;
  928. }
  929. else
  930. {
  931. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  932. }
  933. return ret;
  934. }
  935. const WBEMTimeSpan &WBEMTimeSpan::operator+= ( const WBEMTimeSpan &uAdd )
  936. {
  937. if (IsOk() && uAdd.IsOk())
  938. {
  939. m_Time += uAdd.m_Time ;
  940. }
  941. else
  942. {
  943. Clear();
  944. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  945. }
  946. return *this ;
  947. }
  948. //***************************************************************************
  949. //
  950. // WBEMTimeSpan::operator -(const WBEMTimeSpan &uAdd)
  951. //
  952. // Description: function for adding two WBEMTimeSpan objects.
  953. //
  954. // Return: WBEMTimeSpan object.
  955. //
  956. //***************************************************************************
  957. WBEMTimeSpan WBEMTimeSpan::operator-(const WBEMTimeSpan &uSub) const
  958. {
  959. WBEMTimeSpan ret;
  960. if (IsOk() && uSub.IsOk() && (m_Time >= uSub.m_Time))
  961. {
  962. ret.m_Time = m_Time - uSub.m_Time;
  963. }
  964. else
  965. {
  966. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  967. }
  968. return ret;
  969. }
  970. const WBEMTimeSpan &WBEMTimeSpan::operator-= ( const WBEMTimeSpan &uSub )
  971. {
  972. if (IsOk() && uSub.IsOk() && (m_Time >= uSub.m_Time))
  973. {
  974. m_Time -= uSub.m_Time;
  975. }
  976. else
  977. {
  978. Clear();
  979. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  980. }
  981. return *this;
  982. }
  983. //***************************************************************************
  984. //
  985. // WBEMTimeSpan::GetBSTR(void)
  986. //
  987. // Description: Converts the time which is stored as the number of
  988. // 100 nano second units into a dmtf formatted string
  989. // ddddddddhhmmss.mmmmmm:000
  990. //
  991. // Return: BSTR representation of time, or NULL if error. Note that the
  992. // caller should free up this string!
  993. //
  994. //***************************************************************************
  995. BSTR WBEMTimeSpan::GetBSTR(void) const
  996. {
  997. if(!IsOk())
  998. {
  999. return NULL;
  1000. }
  1001. ULONGLONG Time = m_Time;
  1002. // The /10 is to convert from 100ns to microseconds
  1003. long iMicro = (long)((Time % 10000000) / 10);
  1004. Time /= 10000000;
  1005. int iSec = (int)(Time % 60);
  1006. Time /= 60;
  1007. int iMin = (int)(Time % 60);
  1008. Time /= 60;
  1009. int iHour = (int)(Time % 24);
  1010. Time /= 24;
  1011. BSTR t_String = SysAllocStringLen(NULL, DMTFLEN + 1);
  1012. if ( ! t_String )
  1013. {
  1014. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1015. }
  1016. swprintf(t_String, L"%08I64i%02d%02d%02d.%06ld:000",
  1017. Time, iHour, iMin, iSec, iMicro);
  1018. return t_String ;
  1019. }
  1020. //***************************************************************************
  1021. //
  1022. // WBEMTimeSpan::Gettime_t(void)
  1023. // WBEMTimeSpan::GetFILETIME(void)
  1024. //
  1025. // Description: Converts the time span which is stored as the number of
  1026. // nano seconds into common stuctures.
  1027. //
  1028. // Return: TRUE if OK.
  1029. //
  1030. //***************************************************************************
  1031. BOOL WBEMTimeSpan::Gettime_t(time_t * ptime_t) const
  1032. {
  1033. ASSERT_BREAK(DEPRECATED);
  1034. if(!IsOk())
  1035. {
  1036. return FALSE;
  1037. }
  1038. *ptime_t = (DWORD)(m_Time / 10000000);
  1039. return TRUE;
  1040. }
  1041. BOOL WBEMTimeSpan::GetFILETIME(FILETIME * pst) const
  1042. {
  1043. ASSERT_BREAK(DEPRECATED);
  1044. if(!IsOk())
  1045. {
  1046. return FALSE;
  1047. }
  1048. ULONGLONG uTemp;
  1049. uTemp = m_Time;
  1050. ui64ToFileTime(&uTemp,pst);
  1051. return TRUE;
  1052. }