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.

1189 lines
31 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. //***************************************************************************
  72. //
  73. // SCODE CWbemDateTime::get_Value
  74. //
  75. // DESCRIPTION:
  76. //
  77. // Retrieve the DMTF datetime value
  78. //
  79. // PARAMETERS:
  80. //
  81. // pbsValue pointer to BSTR to hold value on return
  82. //
  83. // RETURN VALUES:
  84. //
  85. // WBEM_S_NO_ERROR success
  86. // WBEM_E_INVALID_PARAMETER bad input parameters
  87. // WBEM_E_FAILED otherwise
  88. //
  89. //***************************************************************************
  90. HRESULT CWbemDateTime :: GetValue ( BSTR *pbsValue)
  91. {
  92. HRESULT hr = WBEM_E_FAILED;
  93. if (NULL == pbsValue)
  94. hr = WBEM_E_INVALID_PARAMETER;
  95. else
  96. {
  97. wchar_t dmtfValue [WBEMDT_DMTF_LEN + 1];
  98. int dmtfLength = sizeof dmtfValue / sizeof dmtfValue[0];
  99. dmtfValue [WBEMDT_DMTF_LEN] = NULL;
  100. if (m_bIsInterval)
  101. {
  102. // Intervals are easy
  103. hr = StringCchPrintf (dmtfValue, dmtfLength , L"%08d%02d%02d%02d.%06d:000", m_iDay,
  104. m_iHours, m_iMinutes, m_iSeconds, m_iMicroseconds);
  105. }
  106. else
  107. {
  108. if (m_bYearSpecified)
  109. hr = StringCchPrintf(dmtfValue, dmtfLength , L"%04d", m_iYear);
  110. else
  111. hr = StringCchCopyW (dmtfValue, dmtfLength, WILD4);
  112. if (m_bMonthSpecified)
  113. hr = StringCchPrintf (dmtfValue + 4, dmtfLength-4, L"%02d", m_iMonth);
  114. else
  115. hr = StringCchCatW (dmtfValue + 4, dmtfLength-4, WILD2);
  116. if (m_bDaySpecified)
  117. hr = StringCchPrintf (dmtfValue + 6, dmtfLength-6, L"%02d", m_iDay);
  118. else
  119. hr = StringCchCatW (dmtfValue + 6, dmtfLength-6, WILD2);
  120. if (m_bHoursSpecified)
  121. hr = StringCchPrintf (dmtfValue + 8, dmtfLength-8, L"%02d", m_iHours);
  122. else
  123. hr = StringCchCatW (dmtfValue + 8, dmtfLength-8, WILD2);
  124. if (m_bMinutesSpecified)
  125. hr = StringCchPrintf (dmtfValue + 10, dmtfLength - 10, L"%02d", m_iMinutes);
  126. else
  127. hr = StringCchCatW (dmtfValue + 10, dmtfLength-10, WILD2);
  128. if (m_bSecondsSpecified)
  129. hr = StringCchPrintf (dmtfValue + 12, dmtfLength-12, L"%02d.", m_iSeconds);
  130. else
  131. {
  132. hr = StringCchCatW (dmtfValue + 12, dmtfLength-12, WILD2);
  133. hr = StringCchCatW (dmtfValue + 14, dmtfLength-14, L".");
  134. }
  135. if (m_bMicrosecondsSpecified)
  136. hr = StringCchPrintf (dmtfValue + 15, dmtfLength - 15, L"%06d", m_iMicroseconds);
  137. else
  138. hr = StringCchCatW (dmtfValue + 15, dmtfLength-15, WILD6);
  139. if (m_bUTCSpecified)
  140. hr = StringCchPrintf (dmtfValue + 21, dmtfLength-21, L"%C%03d", (0 <= m_iUTC) ? L'+' : L'-',
  141. (0 <= m_iUTC) ? m_iUTC : -m_iUTC);
  142. else
  143. {
  144. hr = StringCchCatW (dmtfValue + 21, dmtfLength-21, L"+");
  145. hr = StringCchCatW (dmtfValue + 22, dmtfLength-22, WILD3);
  146. }
  147. }
  148. if (SUCCEEDED(hr))
  149. {
  150. *pbsValue = SysAllocString (dmtfValue);
  151. if ( *pbsValue == NULL )
  152. {
  153. hr = WBEM_E_OUT_OF_MEMORY ;
  154. }
  155. else
  156. {
  157. hr = WBEM_S_NO_ERROR;
  158. }
  159. }
  160. }
  161. return hr;
  162. }
  163. //***************************************************************************
  164. //
  165. // SCODE CWbemDateTime::put_Value
  166. //
  167. // DESCRIPTION:
  168. //
  169. // Retrieve the DMTF datetime value
  170. //
  171. // PARAMETERS:
  172. //
  173. // bsValue new value
  174. //
  175. // RETURN VALUES:
  176. //
  177. // WBEM_S_NO_ERROR success
  178. // WBEM_E_INVALID_PARAMETER bad input parameters
  179. // WBEM_E_FAILED otherwise
  180. //
  181. //***************************************************************************
  182. HRESULT CWbemDateTime::PutValue( BSTR bsValue)
  183. {
  184. HRESULT hr = WBEM_E_INVALID_SYNTAX;
  185. // First check that the value is the right length
  186. if (bsValue && (WBEMDT_DMTF_LEN == wcslen (bsValue)))
  187. {
  188. bool err = false;
  189. long iYear = 0, iMonth = 1, iDay = 1, iHours = 0, iMinutes = 0,
  190. iSeconds = 0, iMicroseconds = 0, iUTC = 0;
  191. VARIANT_BOOL bYearSpecified = VARIANT_TRUE,
  192. bMonthSpecified = VARIANT_TRUE,
  193. bDaySpecified = VARIANT_TRUE,
  194. bHoursSpecified = VARIANT_TRUE,
  195. bMinutesSpecified = VARIANT_TRUE,
  196. bSecondsSpecified = VARIANT_TRUE,
  197. bMicrosecondsSpecified = VARIANT_TRUE,
  198. bUTCSpecified = VARIANT_TRUE,
  199. bIsInterval = VARIANT_TRUE;
  200. LPWSTR pValue = (LPWSTR) bsValue;
  201. // Check whether its an interval
  202. if (ISINTERVAL(pValue [WBEMDT_DMTF_UPOS]))
  203. {
  204. // Years and months are as nothing to us in interval land
  205. bYearSpecified = VARIANT_FALSE;
  206. bMonthSpecified = VARIANT_FALSE;
  207. // Check that everything is a digit apart from
  208. // the interval separator
  209. for (int i = 0; i < WBEMDT_DMTF_LEN; i++)
  210. {
  211. if ((WBEMDT_DMTF_UPOS != i) &&
  212. (WBEMDT_DMTF_SPOS != i) && !wbem_iswdigit (pValue [i]))
  213. {
  214. err = true;
  215. break;
  216. }
  217. }
  218. if (!err)
  219. {
  220. // Now check all is within bounds
  221. err = !(CheckField (pValue, 8, bDaySpecified, iDay, WBEMDT_MAX_DAYINT, WBEMDT_MIN_DAYINT) &&
  222. (VARIANT_TRUE == bDaySpecified) &&
  223. CheckField (pValue+8, 2, bHoursSpecified, iHours, WBEMDT_MAX_HOURS, WBEMDT_MIN_HOURS) &&
  224. (VARIANT_TRUE == bHoursSpecified) &&
  225. CheckField (pValue+10, 2, bMinutesSpecified, iMinutes, WBEMDT_MAX_MINUTES, WBEMDT_MIN_MINUTES) &&
  226. (VARIANT_TRUE == bMinutesSpecified) &&
  227. CheckField (pValue+12, 2, bSecondsSpecified, iSeconds, WBEMDT_MAX_SECONDS, WBEMDT_MIN_SECONDS) &&
  228. (VARIANT_TRUE == bSecondsSpecified) &&
  229. (ISDOT(pValue [WBEMDT_DMTF_SPOS])) &&
  230. CheckField (pValue+15, 6, bMicrosecondsSpecified, iMicroseconds, WBEMDT_MAX_MICROSEC, WBEMDT_MIN_MICROSEC) &&
  231. (VARIANT_TRUE == bMicrosecondsSpecified) &&
  232. CheckUTC (pValue+21, bUTCSpecified, iUTC, false));
  233. }
  234. }
  235. else
  236. {
  237. // assume it's a datetime
  238. bIsInterval = VARIANT_FALSE;
  239. err = !(CheckField (pValue, 4, bYearSpecified, iYear, WBEMDT_MAX_YEAR, WBEMDT_MIN_YEAR) &&
  240. CheckField (pValue+4, 2, bMonthSpecified, iMonth, WBEMDT_MAX_MONTH, WBEMDT_MIN_MONTH) &&
  241. CheckField (pValue+6, 2, bDaySpecified, iDay, WBEMDT_MAX_DAY, WBEMDT_MIN_DAY) &&
  242. CheckField (pValue+8, 2, bHoursSpecified, iHours, WBEMDT_MAX_HOURS, WBEMDT_MIN_HOURS) &&
  243. CheckField (pValue+10, 2, bMinutesSpecified, iMinutes, WBEMDT_MAX_MINUTES, WBEMDT_MIN_MINUTES) &&
  244. CheckField (pValue+12, 2, bSecondsSpecified, iSeconds, WBEMDT_MAX_SECONDS, WBEMDT_MIN_SECONDS) &&
  245. (ISDOT(pValue [WBEMDT_DMTF_SPOS])) &&
  246. CheckField (pValue+15, 6, bMicrosecondsSpecified, iMicroseconds, WBEMDT_MAX_MICROSEC, WBEMDT_MIN_MICROSEC) &&
  247. CheckUTC (pValue+21, bUTCSpecified, iUTC));
  248. }
  249. if (!err)
  250. {
  251. m_iYear = iYear;
  252. m_iMonth = iMonth;
  253. m_iDay = iDay;
  254. m_iHours = iHours;
  255. m_iMinutes = iMinutes;
  256. m_iSeconds = iSeconds;
  257. m_iMicroseconds = iMicroseconds;
  258. m_iUTC = iUTC;
  259. m_bYearSpecified = bYearSpecified;
  260. m_bMonthSpecified = bMonthSpecified;
  261. m_bDaySpecified = bDaySpecified;
  262. m_bHoursSpecified = bHoursSpecified;
  263. m_bMinutesSpecified = bMinutesSpecified;
  264. m_bSecondsSpecified = bSecondsSpecified;
  265. m_bMicrosecondsSpecified = bMicrosecondsSpecified;
  266. m_bUTCSpecified = bUTCSpecified;
  267. m_bIsInterval = bIsInterval;
  268. hr = S_OK;
  269. }
  270. }
  271. return hr;
  272. }
  273. //***************************************************************************
  274. //
  275. // SCODE CWbemDateTime::CheckField
  276. //
  277. // DESCRIPTION:
  278. //
  279. // Check a string-based datetime field for correctness
  280. //
  281. // PARAMETERS:
  282. //
  283. // pValue pointer to the value to check
  284. // len number of characters in the value
  285. // bIsSpecified on return defines whether value is wildcard
  286. // iValue on return specifies integer value (if not wildcard)
  287. // maxValue maximum numeric value allowed for this field
  288. // minValue minimum numeric value allowed for this field
  289. //
  290. // RETURN VALUES:
  291. //
  292. // true if value parsed ok, false otherwise
  293. //
  294. //***************************************************************************
  295. bool CWbemDateTime::CheckField (
  296. LPWSTR pValue,
  297. ULONG len,
  298. VARIANT_BOOL &bIsSpecified,
  299. long &iValue,
  300. long maxValue,
  301. long minValue
  302. )
  303. {
  304. bool status = true;
  305. bIsSpecified = VARIANT_FALSE;
  306. for (ULONG i = 0; i < len; i++)
  307. {
  308. if (ISWILD(pValue [i]))
  309. {
  310. if (VARIANT_TRUE == bIsSpecified)
  311. {
  312. status = false;
  313. break;
  314. }
  315. }
  316. else if (!wbem_iswdigit (pValue [i]))
  317. {
  318. status = false;
  319. break;
  320. }
  321. else
  322. bIsSpecified = VARIANT_TRUE;
  323. }
  324. if (status)
  325. {
  326. if (VARIANT_TRUE == bIsSpecified)
  327. {
  328. wchar_t *dummy = NULL;
  329. wchar_t temp [12];
  330. if ( len > ( ( sizeof ( temp ) / sizeof ( wchar_t ) ) - 1 ) )
  331. {
  332. return false ;
  333. }
  334. if ( FAILED ( StringCchCopyNW ( temp , ( sizeof ( temp ) / sizeof ( wchar_t ) ) , pValue, len ) ) )
  335. {
  336. return false ;
  337. }
  338. temp [len] = NULL;
  339. iValue = wcstol (temp, &dummy, 10);
  340. }
  341. }
  342. return status;
  343. }
  344. //***************************************************************************
  345. //
  346. // SCODE CWbemDateTime::CheckUTC
  347. //
  348. // DESCRIPTION:
  349. //
  350. // Check a string-based UTC field for correctness
  351. //
  352. // PARAMETERS:
  353. //
  354. // pValue pointer to the value to check
  355. // bIsSpecified on return defines whether value is wildcard
  356. // iValue on return specifies integer value (if not wildcard)
  357. // bParseSign whether first character should be a sign (+/-) or
  358. // a : (for intervals)
  359. //
  360. // RETURN VALUES:
  361. //
  362. // true if value parsed ok, false otherwise
  363. //
  364. //***************************************************************************
  365. bool CWbemDateTime::CheckUTC (
  366. LPWSTR pValue,
  367. VARIANT_BOOL &bIsSpecified,
  368. long &iValue,
  369. bool bParseSign
  370. )
  371. {
  372. bool status = true;
  373. bool lessThanZero = false;
  374. bIsSpecified = VARIANT_FALSE;
  375. // Check if we have a signed offset
  376. if (bParseSign)
  377. {
  378. if (ISMINUS(pValue [0]))
  379. lessThanZero = true;
  380. else if (!ISPLUS(pValue [0]))
  381. status = false;
  382. }
  383. else
  384. {
  385. if (!ISINTERVAL(pValue[0]))
  386. status = false;
  387. }
  388. if (status)
  389. {
  390. // Check remaining are digits or wildcars
  391. for (int i = 1; i < 4; i++)
  392. {
  393. if (ISWILD(pValue [i]))
  394. {
  395. if (VARIANT_TRUE == bIsSpecified)
  396. {
  397. status = false;
  398. break;
  399. }
  400. }
  401. else if (!wbem_iswdigit (pValue [i]))
  402. {
  403. status = false;
  404. break;
  405. }
  406. else
  407. bIsSpecified = VARIANT_TRUE;
  408. }
  409. }
  410. if (status)
  411. {
  412. if (VARIANT_TRUE == bIsSpecified)
  413. {
  414. wchar_t *dummy = NULL;
  415. wchar_t temp [4];
  416. wcsncpy (temp, pValue+1, 3);
  417. temp [3] = NULL;
  418. iValue = wcstol (temp, &dummy, 10);
  419. if (lessThanZero)
  420. iValue = -iValue;
  421. }
  422. }
  423. return status;
  424. }
  425. //***************************************************************************
  426. //
  427. // SCODE CWbemDateTime::GetVarDate
  428. //
  429. // DESCRIPTION:
  430. //
  431. // Retrieve the value in Variant form
  432. //
  433. // PARAMETERS:
  434. //
  435. // bIsLocal whether to return a local or UTC value
  436. // pVarDate holds result on successful return
  437. //
  438. // RETURN VALUES:
  439. //
  440. // WBEM_S_NO_ERROR success
  441. // WBEM_E_INVALID_SYNTAX input value is bad
  442. // WBEM_E_FAILED otherwise
  443. //
  444. //***************************************************************************
  445. HRESULT CWbemDateTime::GetVarDate(
  446. IN VARIANT_BOOL bIsLocal,
  447. OUT DATE *pVarDate)
  448. {
  449. HRESULT hr = WBEM_E_INVALID_SYNTAX;
  450. if (NULL == pVarDate)
  451. hr = WBEM_E_INVALID_PARAMETER;
  452. else
  453. {
  454. // We cannot perform this operation for interval
  455. // or wildcarded values
  456. if ((VARIANT_TRUE == m_bIsInterval) ||
  457. (VARIANT_FALSE == m_bYearSpecified) ||
  458. (VARIANT_FALSE == m_bMonthSpecified) ||
  459. (VARIANT_FALSE == m_bDaySpecified) ||
  460. (VARIANT_FALSE == m_bHoursSpecified) ||
  461. (VARIANT_FALSE == m_bMinutesSpecified) ||
  462. (VARIANT_FALSE == m_bSecondsSpecified) ||
  463. (VARIANT_FALSE == m_bMicrosecondsSpecified) ||
  464. (VARIANT_FALSE == m_bUTCSpecified))
  465. {
  466. hr = WBEM_E_FAILED;
  467. }
  468. else
  469. {
  470. SYSTEMTIME sysTime;
  471. sysTime.wYear = ( WORD ) m_iYear;
  472. sysTime.wMonth = ( WORD ) m_iMonth;
  473. sysTime.wDay = ( WORD ) m_iDay;
  474. sysTime.wHour = ( WORD ) m_iHours;
  475. sysTime.wMinute = ( WORD ) m_iMinutes;
  476. sysTime.wSecond = ( WORD ) m_iSeconds;
  477. sysTime.wMilliseconds = ( WORD ) ( m_iMicroseconds/1000 ) ;
  478. if (VARIANT_TRUE == bIsLocal)
  479. {
  480. // Need to convert this to a local DATE value
  481. // This requires that we switch the currently stored
  482. // time to one for the appropriate timezone, lop off
  483. // the UTC and set the rest in a variant.
  484. // Coerce the time to GMT first
  485. WBEMTime wbemTime (sysTime);
  486. if (!wbemTime.GetDMTF (sysTime))
  487. return WBEM_E_INVALID_SYNTAX;
  488. }
  489. double dVarDate;
  490. if (SystemTimeToVariantTime (&sysTime, &dVarDate))
  491. {
  492. *pVarDate = dVarDate;
  493. hr = S_OK;
  494. }
  495. }
  496. }
  497. return hr;
  498. }
  499. //***************************************************************************
  500. //
  501. // SCODE CWbemDateTime::SetVarDate
  502. //
  503. // DESCRIPTION:
  504. //
  505. // Set the value in Variant form
  506. //
  507. // PARAMETERS:
  508. //
  509. // dVarDate the new value
  510. // bIsLocal whether to treat as local or UTC value
  511. //
  512. // RETURN VALUES:
  513. //
  514. // WBEM_S_NO_ERROR success
  515. // WBEM_E_INVALID_SYNTAX input value is bad
  516. //
  517. //***************************************************************************
  518. HRESULT CWbemDateTime::SetVarDate(
  519. /*[in]*/ DATE dVarDate,
  520. /*[in, optional]*/ VARIANT_BOOL bIsLocal)
  521. {
  522. HRESULT hr = WBEM_E_INVALID_SYNTAX;
  523. SYSTEMTIME sysTime;
  524. if (TRUE == VariantTimeToSystemTime (dVarDate, &sysTime))
  525. {
  526. long offset = 0;
  527. if (VARIANT_TRUE == bIsLocal)
  528. {
  529. WBEMTime wbemTime (sysTime);
  530. if (!wbemTime.GetDMTF (sysTime, offset))
  531. return WBEM_E_INVALID_SYNTAX;
  532. }
  533. m_iYear = sysTime.wYear;
  534. m_iMonth = sysTime.wMonth;
  535. m_iDay = sysTime.wDay;
  536. m_iHours = sysTime.wHour;
  537. m_iMinutes = sysTime.wMinute;
  538. m_iSeconds = sysTime.wSecond;
  539. m_iMicroseconds = sysTime.wMilliseconds * 1000;
  540. m_iUTC = offset;
  541. m_bYearSpecified = VARIANT_TRUE,
  542. m_bMonthSpecified = VARIANT_TRUE,
  543. m_bDaySpecified = VARIANT_TRUE,
  544. m_bHoursSpecified = VARIANT_TRUE,
  545. m_bMinutesSpecified = VARIANT_TRUE,
  546. m_bSecondsSpecified = VARIANT_TRUE,
  547. m_bMicrosecondsSpecified = VARIANT_TRUE,
  548. m_bUTCSpecified = VARIANT_TRUE,
  549. m_bIsInterval = VARIANT_FALSE;
  550. hr = S_OK;
  551. }
  552. return hr;
  553. }
  554. //***************************************************************************
  555. //
  556. // SCODE CWbemDateTime::SetVarDate
  557. //
  558. // DESCRIPTION:
  559. //
  560. // Set the value in Variant form
  561. //
  562. // PARAMETERS:
  563. //
  564. // dVarDate the new value
  565. // bIsLocal whether to treat as local or UTC value
  566. //
  567. // RETURN VALUES:
  568. //
  569. // WBEM_S_NO_ERROR success
  570. // WBEM_E_INVALID_SYNTAX input value is bad
  571. //
  572. //***************************************************************************
  573. HRESULT CWbemDateTime::SetFileTimeDate(
  574. /*[in]*/ FILETIME fFileTime,
  575. /*[in, optional]*/ VARIANT_BOOL bIsLocal)
  576. {
  577. HRESULT hr = WBEM_E_INVALID_SYNTAX;
  578. SYSTEMTIME sysTime;
  579. long offset = 0;
  580. if (VARIANT_TRUE == bIsLocal)
  581. {
  582. WBEMTime wbemTime (fFileTime);
  583. if (!wbemTime.GetDMTF (sysTime, offset))
  584. return WBEM_E_INVALID_SYNTAX;
  585. }
  586. else
  587. {
  588. WBEMTime wbemTime (fFileTime);
  589. wbemTime.GetSYSTEMTIME(&sysTime);
  590. }
  591. m_iYear = sysTime.wYear;
  592. m_iMonth = sysTime.wMonth;
  593. m_iDay = sysTime.wDay;
  594. m_iHours = sysTime.wHour;
  595. m_iMinutes = sysTime.wMinute;
  596. m_iSeconds = sysTime.wSecond;
  597. m_iMicroseconds = sysTime.wMilliseconds * 1000;
  598. m_iUTC = offset;
  599. m_bYearSpecified = VARIANT_TRUE,
  600. m_bMonthSpecified = VARIANT_TRUE,
  601. m_bDaySpecified = VARIANT_TRUE,
  602. m_bHoursSpecified = VARIANT_TRUE,
  603. m_bMinutesSpecified = VARIANT_TRUE,
  604. m_bSecondsSpecified = VARIANT_TRUE,
  605. m_bMicrosecondsSpecified = VARIANT_TRUE,
  606. m_bUTCSpecified = VARIANT_TRUE,
  607. m_bIsInterval = VARIANT_FALSE;
  608. hr = S_OK;
  609. return hr;
  610. }
  611. // These are here rather than wbemtime.h so we don't have to doc/support
  612. #define INVALID_TIME_FORMAT 0
  613. #define INVALID_TIME_ARITHMETIC 0
  614. #define BAD_TIMEZONE 0
  615. //***************************************************************************
  616. //
  617. // FileTimeToui64
  618. // ui64ToFileTime
  619. //
  620. // Description: Conversion routines for going between FILETIME structures
  621. // and __int64.
  622. //
  623. //***************************************************************************
  624. static void FileTimeToui64(const FILETIME *pft, ULONGLONG *p64)
  625. {
  626. *p64 = pft->dwHighDateTime;
  627. *p64 = *p64 << 32;
  628. *p64 |= pft->dwLowDateTime;
  629. }
  630. static void ui64ToFileTime(const ULONGLONG *p64,FILETIME *pft)
  631. {
  632. unsigned __int64 uTemp = *p64;
  633. pft->dwLowDateTime = (DWORD)uTemp;
  634. uTemp = uTemp >> 32;
  635. pft->dwHighDateTime = (DWORD)uTemp;
  636. }
  637. static int CompareSYSTEMTIME(const SYSTEMTIME *pst1, const SYSTEMTIME *pst2)
  638. {
  639. FILETIME ft1, ft2;
  640. SystemTimeToFileTime(pst1, &ft1);
  641. SystemTimeToFileTime(pst2, &ft2);
  642. return CompareFileTime(&ft1, &ft2);
  643. }
  644. // This function is used to convert the relative values that come
  645. // back from GetTimeZoneInformation into an actual date for the year
  646. // in question. The system time structure that is passed in is updated
  647. // to contain the absolute values.
  648. static void DayInMonthToAbsolute(SYSTEMTIME *pst, const WORD wYear)
  649. {
  650. const static int _lpdays[] = {
  651. -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  652. };
  653. const static int _days[] = {
  654. -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
  655. };
  656. SHORT shYearDay;
  657. // If this is not 0, this is not a relative date
  658. if (pst->wYear == 0)
  659. {
  660. // Was that year a leap year?
  661. BOOL bLeap = ( (( wYear % 400) == 0) || ((( wYear % 4) == 0) && (( wYear % 100) != 0)));
  662. // Figure out the day of the year for the first day of the month in question
  663. if (bLeap)
  664. shYearDay = 1 + _lpdays[pst->wMonth - 1];
  665. else
  666. shYearDay = 1 + _days[pst->wMonth - 1];
  667. // Now, figure out how many leap days there have been since 1/1/1601
  668. WORD yc = wYear - 1601;
  669. WORD y4 = (yc) / 4;
  670. WORD y100 = (yc) / 100;
  671. WORD y400 = (yc) / 400;
  672. // This will tell us the day of the week for the first day of the month in question.
  673. // The '1 +' reflects the fact that 1/1/1601 was a monday (figures). You might ask,
  674. // 'why do we care what day of the week this is?' Well, I'll tell you. The way
  675. // daylight savings time is defined is with things like 'the last sunday of the month
  676. // of october.' Kinda helps to know what day that is.
  677. SHORT monthdow = (1 + (yc * 365 + y4 + y400 - y100) + shYearDay) % 7;
  678. if ( monthdow < pst->wDayOfWeek )
  679. shYearDay += (pst->wDayOfWeek - monthdow) + (pst->wDay - 1) * 7;
  680. else
  681. shYearDay += (pst->wDayOfWeek - monthdow) + pst->wDay * 7;
  682. /*
  683. * May have to adjust the calculation above if week == 5 (meaning
  684. * the last instance of the day in the month). Check if yearday falls
  685. * beyond month and adjust accordingly.
  686. */
  687. if ( (pst->wDay == 5) &&
  688. (shYearDay > (bLeap ? _lpdays[pst->wMonth] :
  689. _days[pst->wMonth])) )
  690. {
  691. shYearDay -= 7;
  692. }
  693. // Now update the structure.
  694. pst->wYear = wYear;
  695. pst->wDay = shYearDay - (bLeap ? _lpdays[pst->wMonth - 1] :
  696. _days[pst->wMonth - 1]);
  697. }
  698. }
  699. // **************************************************************************
  700. // These are static to WBEMTIME, which means they CAN be called from outside
  701. // wbemtime
  702. CWbemDateTime::WBEMTime :: WBEMTime ( const FILETIME &ft )
  703. {
  704. FileTimeToui64(&ft, &m_uTime);
  705. }
  706. LONG CWbemDateTime::WBEMTime::GetLocalOffsetForDate(const SYSTEMTIME *pst)
  707. {
  708. TIME_ZONE_INFORMATION tzTime;
  709. DWORD dwRes = GetTimeZoneInformation(&tzTime);
  710. LONG lRes = 0xffffffff;
  711. switch (dwRes)
  712. {
  713. case TIME_ZONE_ID_UNKNOWN:
  714. {
  715. // Read tz, but no dst defined in this zone
  716. lRes = tzTime.Bias * -1;
  717. break;
  718. }
  719. case TIME_ZONE_ID_STANDARD:
  720. case TIME_ZONE_ID_DAYLIGHT:
  721. {
  722. // Convert the relative dates to absolute dates
  723. DayInMonthToAbsolute(&tzTime.DaylightDate, pst->wYear);
  724. DayInMonthToAbsolute(&tzTime.StandardDate, pst->wYear);
  725. if ( CompareSYSTEMTIME(&tzTime.DaylightDate, &tzTime.StandardDate) < 0 )
  726. {
  727. /*
  728. * Northern hemisphere ordering
  729. */
  730. if ( CompareSYSTEMTIME(pst, &tzTime.DaylightDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.StandardDate) > 0)
  731. {
  732. lRes = tzTime.Bias * -1;
  733. }
  734. else
  735. {
  736. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  737. }
  738. }
  739. else
  740. {
  741. /*
  742. * Southern hemisphere ordering
  743. */
  744. if ( CompareSYSTEMTIME(pst, &tzTime.StandardDate) < 0 || CompareSYSTEMTIME(pst, &tzTime.DaylightDate) > 0)
  745. {
  746. lRes = (tzTime.Bias + tzTime.DaylightBias) * -1;
  747. }
  748. else
  749. {
  750. lRes = tzTime.Bias * -1;
  751. }
  752. }
  753. break;
  754. }
  755. case TIME_ZONE_ID_INVALID:
  756. default:
  757. {
  758. // Can't read the timezone info
  759. ASSERT_BREAK(BAD_TIMEZONE);
  760. break;
  761. }
  762. }
  763. return lRes;
  764. }
  765. ///////////////////////////////////////////////////////////////////////////
  766. // WBEMTime - This class holds time values.
  767. //***************************************************************************
  768. //
  769. // WBEMTime::operator+(const WBEMTimeSpan &uAdd)
  770. //
  771. // Description: dummy function for adding two WBEMTime. It doesnt really
  772. // make sense to add two date, but this is here for Tomas's template.
  773. //
  774. // Return: WBEMTime object.
  775. //
  776. //***************************************************************************
  777. CWbemDateTime::WBEMTime CWbemDateTime::WBEMTime::operator+(const WBEMTimeSpan &uAdd) const
  778. {
  779. WBEMTime ret;
  780. if (IsOk())
  781. {
  782. ret.m_uTime = m_uTime + uAdd.m_Time;
  783. }
  784. else
  785. {
  786. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  787. }
  788. return ret;
  789. }
  790. //***************************************************************************
  791. //
  792. // WBEMTime::operator=(const SYSTEMTIME)
  793. //
  794. // Description: Assignment operator which is also used by the constructor.
  795. // This takes a standard WIN32 SYSTEMTIME stucture.
  796. //
  797. // Return: WBEMTime object.
  798. //
  799. //***************************************************************************
  800. const CWbemDateTime::WBEMTime & CWbemDateTime::WBEMTime::operator=(const SYSTEMTIME & st)
  801. {
  802. Clear(); // set when properly assigned
  803. FILETIME t_ft;
  804. if ( SystemTimeToFileTime(&st, &t_ft) )
  805. {
  806. // now assign using a FILETIME.
  807. *this = t_ft;
  808. }
  809. else
  810. {
  811. ASSERT_BREAK(INVALID_TIME_FORMAT);
  812. }
  813. return *this;
  814. }
  815. //***************************************************************************
  816. //
  817. // WBEMTime::operator=(const FILETIME)
  818. //
  819. // Description: Assignment operator which is also used by the constructor.
  820. // This takes a standard WIN32 FILETIME stucture.
  821. //
  822. // Return: WBEMTime object.
  823. //
  824. //***************************************************************************
  825. const CWbemDateTime::WBEMTime & CWbemDateTime::WBEMTime::operator=(const FILETIME & ft)
  826. {
  827. FileTimeToui64(&ft, &m_uTime);
  828. return *this;
  829. }
  830. //***************************************************************************
  831. //
  832. // WBEMTime::operator-(const WBEMTime & sub)
  833. //
  834. // Description: returns a WBEMTimeSpan object as the difference between
  835. // two WBEMTime objects.
  836. //
  837. // Return: WBEMTimeSpan object.
  838. //
  839. //***************************************************************************
  840. CWbemDateTime::WBEMTime CWbemDateTime::WBEMTime::operator-(const WBEMTimeSpan & sub) const
  841. {
  842. WBEMTime ret;
  843. if (IsOk() && (m_uTime >= sub.m_Time))
  844. {
  845. ret.m_uTime = m_uTime - sub.m_Time;
  846. }
  847. else
  848. {
  849. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  850. }
  851. return ret;
  852. }
  853. //***************************************************************************
  854. //
  855. // WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst)
  856. //
  857. // Return: TRUE if OK.
  858. //
  859. //***************************************************************************
  860. BOOL CWbemDateTime::WBEMTime::GetSYSTEMTIME(SYSTEMTIME * pst) const
  861. {
  862. if ((pst == NULL) || (!IsOk()))
  863. {
  864. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  865. return FALSE;
  866. }
  867. FILETIME t_ft;
  868. if (GetFILETIME(&t_ft))
  869. {
  870. if (!FileTimeToSystemTime(&t_ft, pst))
  871. {
  872. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  873. return FALSE;
  874. }
  875. }
  876. else
  877. {
  878. return FALSE;
  879. }
  880. return TRUE;
  881. }
  882. //***************************************************************************
  883. //
  884. // WBEMTime::GetFILETIME(FILETIME * pst)
  885. //
  886. // Return: TRUE if OK.
  887. //
  888. //***************************************************************************
  889. BOOL CWbemDateTime::WBEMTime::GetFILETIME(FILETIME * pft) const
  890. {
  891. if ((pft == NULL) || (!IsOk()))
  892. {
  893. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  894. return FALSE;
  895. }
  896. ui64ToFileTime(&m_uTime, pft);
  897. return TRUE;
  898. }
  899. //***************************************************************************
  900. //
  901. // BSTR WBEMTime::GetDMTF(SYSTEMTIME &st, long &offset)
  902. //
  903. // Description: Gets the time in DMTF string local datetime format as a
  904. // SYSTEMTIME.
  905. //
  906. // Return: NULL if not OK.
  907. //
  908. //***************************************************************************
  909. BOOL CWbemDateTime::WBEMTime::GetDMTF(SYSTEMTIME &st, long &offset) const
  910. {
  911. if (!IsOk())
  912. {
  913. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  914. return FALSE;
  915. }
  916. // If the date to be converted is within 12 hours of
  917. // 1/1/1601, return the greenwich time
  918. ULONGLONG t_ConversionZone = 12L * 60L * 60L ;
  919. t_ConversionZone = t_ConversionZone * 10000000L ;
  920. if ( m_uTime < t_ConversionZone )
  921. {
  922. if(!GetSYSTEMTIME(&st))
  923. return FALSE;
  924. }
  925. else
  926. {
  927. if (GetSYSTEMTIME(&st))
  928. {
  929. offset = GetLocalOffsetForDate(&st);
  930. WBEMTime wt;
  931. if (offset >= 0)
  932. wt = *this - WBEMTimeSpan(offset);
  933. else
  934. wt = *this + WBEMTimeSpan(-offset);
  935. wt.GetSYSTEMTIME(&st);
  936. }
  937. else
  938. return FALSE;
  939. }
  940. return TRUE ;
  941. }
  942. //***************************************************************************
  943. //
  944. // BSTR WBEMTime::GetDMTF(SYSTEMTIME &st)
  945. //
  946. // Description: Gets the time in as local SYSTEMTIME.
  947. //
  948. // Return: NULL if not OK.
  949. //
  950. //***************************************************************************
  951. BOOL CWbemDateTime::WBEMTime::GetDMTF(SYSTEMTIME &st) const
  952. {
  953. if (!IsOk())
  954. {
  955. ASSERT_BREAK(INVALID_TIME_ARITHMETIC);
  956. return FALSE;
  957. }
  958. // If the date to be converted is within 12 hours of
  959. // 1/1/1601, return the greenwich time
  960. ULONGLONG t_ConversionZone = 12L * 60L * 60L ;
  961. t_ConversionZone = t_ConversionZone * 10000000L ;
  962. if ( m_uTime < t_ConversionZone )
  963. {
  964. if(!GetSYSTEMTIME(&st))
  965. return FALSE;
  966. }
  967. else
  968. {
  969. if (GetSYSTEMTIME(&st))
  970. {
  971. long offset = GetLocalOffsetForDate(&st);
  972. WBEMTime wt;
  973. if (offset >= 0)
  974. wt = *this + WBEMTimeSpan(offset);
  975. else
  976. wt = *this - WBEMTimeSpan(-offset);
  977. wt.GetSYSTEMTIME(&st);
  978. }
  979. else
  980. return FALSE;
  981. }
  982. return TRUE ;
  983. }
  984. BOOL CWbemDateTime::Preceeds ( CWbemDateTime &a_Time )
  985. {
  986. BOOL t_Truth = TRUE ;
  987. SYSTEMTIME t_ThisTime ;
  988. t_ThisTime.wYear = ( WORD ) m_iYear;
  989. t_ThisTime.wMonth = ( WORD ) m_iMonth;
  990. t_ThisTime.wDay = ( WORD ) m_iDay;
  991. t_ThisTime.wHour = ( WORD ) m_iHours;
  992. t_ThisTime.wMinute = ( WORD ) m_iMinutes;
  993. t_ThisTime.wSecond = ( WORD ) m_iSeconds;
  994. t_ThisTime.wMilliseconds = ( WORD ) ( m_iMicroseconds/1000 ) ;
  995. SYSTEMTIME t_ArgTime ;
  996. t_ArgTime.wYear = ( WORD ) a_Time.m_iYear;
  997. t_ArgTime.wMonth = ( WORD ) a_Time.m_iMonth;
  998. t_ArgTime.wDay = ( WORD ) a_Time.m_iDay;
  999. t_ArgTime.wHour = ( WORD ) a_Time.m_iHours;
  1000. t_ArgTime.wMinute = ( WORD ) a_Time.m_iMinutes;
  1001. t_ArgTime.wSecond = ( WORD ) a_Time.m_iSeconds;
  1002. t_ArgTime.wMilliseconds = ( WORD ) ( a_Time.m_iMicroseconds/1000 ) ;
  1003. t_Truth = CompareSYSTEMTIME ( & t_ThisTime , & t_ArgTime ) < 0 ;
  1004. return t_Truth ;
  1005. }
  1006. HRESULT CWbemDateTime::GetSystemTimeDate (
  1007. SYSTEMTIME &fSystemTime
  1008. )
  1009. {
  1010. ZeroMemory ( & fSystemTime , sizeof ( fSystemTime ) ) ;
  1011. fSystemTime.wYear = ( WORD ) m_iYear;
  1012. fSystemTime.wMonth = ( WORD ) m_iMonth;
  1013. fSystemTime.wDay = ( WORD ) m_iDay;
  1014. fSystemTime.wHour = ( WORD ) m_iHours;
  1015. fSystemTime.wMinute = ( WORD ) m_iMinutes;
  1016. fSystemTime.wSecond = ( WORD ) m_iSeconds;
  1017. fSystemTime.wMilliseconds = ( WORD ) ( m_iMicroseconds/1000 ) ;
  1018. return S_OK ;
  1019. }
  1020. HRESULT CWbemDateTime::GetFileTimeDate (
  1021. FILETIME &fFileTime
  1022. )
  1023. {
  1024. SYSTEMTIME fSystemTime ;
  1025. ZeroMemory ( & fSystemTime , sizeof ( fSystemTime ) ) ;
  1026. fSystemTime.wYear = ( WORD ) m_iYear;
  1027. fSystemTime.wMonth = ( WORD ) m_iMonth;
  1028. fSystemTime.wDay = ( WORD ) m_iDay;
  1029. fSystemTime.wHour = ( WORD ) m_iHours;
  1030. fSystemTime.wMinute = ( WORD ) m_iMinutes;
  1031. fSystemTime.wSecond = ( WORD ) m_iSeconds;
  1032. fSystemTime.wMilliseconds = ( WORD ) ( m_iMicroseconds/1000 ) ;
  1033. if ( FileTimeToSystemTime ( & fFileTime , & fSystemTime ) )
  1034. {
  1035. return S_OK ;
  1036. }
  1037. else
  1038. {
  1039. return WBEM_E_FAILED ;
  1040. }
  1041. }