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.

1368 lines
37 KiB

  1. // DateTime.cpp : Implementation of CDateTime
  2. #include "stdafx.h"
  3. #include <regstr.h>
  4. #include <comdef.h>
  5. #include <comutil.h>
  6. #include "SetDateTime.h"
  7. #include "debug.h"
  8. #include "appliancetask.h"
  9. #include "taskctx.h"
  10. #include "DateTime.h"
  11. #include "appsrvcs.h"
  12. #include "appmgrobjs.h"
  13. #include "..\datetimemsg\datetimemsg.h"
  14. //
  15. // Registry location for Time Zone information.
  16. //
  17. TCHAR c_szTimeZones[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
  18. //
  19. // Time Zone data value keys.
  20. //
  21. TCHAR c_szTZDisplayName[] = TEXT("Display");
  22. TCHAR c_szTZStandardName[] = TEXT("Std");
  23. TCHAR c_szTZDaylightName[] = TEXT("Dlt");
  24. TCHAR c_szTZI[] = TEXT("TZI");
  25. #define PARAM_DATE_DAY TEXT("Day")
  26. #define PARAM_DATE_MONTH TEXT("Month")
  27. #define PARAM_DATE_YEAR TEXT("Year")
  28. #define PARAM_TIME_HOUR TEXT("Hour")
  29. #define PARAM_TIME_MINUTE TEXT("Minute")
  30. #define PARAM_TIMEZONE_STANDARDTIME TEXT("StandardName")
  31. #define PARAM_DAYLIGHT_ENABLE TEXT("EnableDayLight")
  32. #define ALERT_LOG_NAME TEXT("MSSAKitComm")
  33. #define ALERT_SOURCE TEXT("")
  34. #define REGKEY_SA_DATETIME TEXT("Software\\Microsoft\\ServerAppliance\\DateTime")
  35. #define REGSTR_VAL_DATETIME_RAISEALERT TEXT("RaiseAlert")
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CDateTime
  38. STDMETHODIMP CDateTime::OnTaskExecute(IUnknown *pTaskContext)
  39. {
  40. HRESULT hr;
  41. ITaskContext *pTaskParameters = NULL;
  42. SET_DATE_TIME_TASK_TYPE sdtChoice;
  43. ASSERT(pTaskContext);
  44. TRACE(("CDateTime::OnTaskExecute"));
  45. hr = pTaskContext->QueryInterface(IID_ITaskContext,
  46. (void **)&pTaskParameters);
  47. if (S_OK != hr)
  48. {
  49. return hr;
  50. }
  51. //
  52. // Check which Task is being executed and call that method
  53. //
  54. sdtChoice = GetMethodName(pTaskParameters);
  55. switch (sdtChoice)
  56. {
  57. case SET_DATE_TIME:
  58. hr = SetDateTime(pTaskParameters);
  59. TRACE1(("SetDateTime returned %X"), hr);
  60. break;
  61. case SET_TIME_ZONE:
  62. hr = SetTimeZone(pTaskParameters);
  63. TRACE1(("SetTimeZone returned %X"), hr);
  64. break;
  65. case RAISE_SETDATETIME_ALERT:
  66. //
  67. // Alert will be raised on OnTaskComplete
  68. //
  69. hr = S_OK;
  70. TRACE(("RaiseSetDateTimeAlert method called"));
  71. break;
  72. default:
  73. TRACE(("GetMethodName() failed to get method name in OnTaskExecute"));
  74. hr = E_INVALIDARG;
  75. break;
  76. }
  77. pTaskParameters->Release();
  78. TRACE1("CDateTime::OnTaskExecute returning %X", hr);
  79. return hr;
  80. }
  81. STDMETHODIMP CDateTime::OnTaskComplete(IUnknown *pTaskContext, LONG lTaskResult)
  82. {
  83. HRESULT hr = E_FAIL;
  84. ITaskContext *pTaskParameters = NULL;
  85. SET_DATE_TIME_TASK_TYPE sdtChoice;
  86. ASSERT(pTaskContext);
  87. TRACE(("CDateTime::OnTaskComplete"));
  88. hr = pTaskContext->QueryInterface(IID_ITaskContext,
  89. (void **)&pTaskParameters);
  90. if (S_OK != hr)
  91. {
  92. return hr;
  93. }
  94. //
  95. // Check which Task is being executed and call that method
  96. //
  97. sdtChoice = GetMethodName(pTaskParameters);
  98. switch (sdtChoice)
  99. {
  100. case SET_DATE_TIME:
  101. if (lTaskResult == SA_TASK_RESULT_COMMIT)
  102. {
  103. //
  104. // Clear any existing DateTime alert and
  105. // do not raise the datetime alert on subsequent boots
  106. //
  107. ClearDateTimeAlert();
  108. DoNotRaiseDateTimeAlert();
  109. TRACE("No rollback in OnTaskComplete");
  110. hr = S_OK;
  111. }
  112. else
  113. {
  114. hr = RollbackSetDateTime(pTaskParameters);
  115. TRACE1(("RollbackSetDateTime returned %X"), hr);
  116. }
  117. break;
  118. case SET_TIME_ZONE:
  119. if (lTaskResult == SA_TASK_RESULT_COMMIT)
  120. {
  121. //
  122. // Clear any existing DateTime alert and
  123. // do not raise the datetime alert on subsequent boots
  124. //
  125. ClearDateTimeAlert();
  126. DoNotRaiseDateTimeAlert();
  127. TRACE("No rollback in OnTaskComplete");
  128. hr = S_OK;
  129. }
  130. else
  131. {
  132. hr = RollbackSetTimeZone(pTaskParameters);
  133. TRACE1(("RollbackSetTimeZone returned %X"), hr);
  134. }
  135. break;
  136. case RAISE_SETDATETIME_ALERT:
  137. if (lTaskResult == SA_TASK_RESULT_COMMIT)
  138. {
  139. if (TRUE == ShouldRaiseDateTimeAlert())
  140. {
  141. hr = RaiseSetDateTimeAlert();
  142. if (FAILED(hr))
  143. {
  144. TRACE1(("RaiseSetDateTimeAlert returned %X"), hr);
  145. }
  146. }
  147. else
  148. {
  149. TRACE("No need to raise the datetime alert");
  150. }
  151. }
  152. else
  153. {
  154. //
  155. // Do nothing on Commit failure
  156. //
  157. hr = S_OK;
  158. }
  159. break;
  160. default:
  161. TRACE(("GetMethodName() failed to get method name in OnTaskComplete"));
  162. hr = E_INVALIDARG;
  163. break;
  164. }
  165. pTaskParameters->Release();
  166. TRACE1("CDateTime::OnTaskComplete returning %X", hr);
  167. return hr;
  168. }
  169. //
  170. // Cut-n-paste from User Management code
  171. //
  172. SET_DATE_TIME_TASK_TYPE CDateTime::GetMethodName(IN ITaskContext *pTaskParameter)
  173. {
  174. BSTR bstrParamName = SysAllocString(TEXT("MethodName"));
  175. HRESULT hr;
  176. VARIANT varValue;
  177. SET_DATE_TIME_TASK_TYPE sdtChoice = NONE_FOUND;
  178. ASSERT(pTaskParameter);
  179. hr = pTaskParameter->GetParameter(bstrParamName,
  180. &varValue);
  181. if (FAILED(hr))
  182. {
  183. TRACE1(("GetParameter failed in CDateTime::GetMethodName %X"),
  184. hr);
  185. }
  186. if (V_VT(&varValue) != VT_BSTR)
  187. {
  188. TRACE1(("Non-strint(%X) parameter received in GetParameter in CSAUserTasks::GetMethodName"), V_VT(&varValue));
  189. hr = E_INVALIDARG;
  190. goto End;
  191. }
  192. if (lstrcmp(V_BSTR(&varValue), SET_DATE_TIME_TASK) == 0)
  193. {
  194. sdtChoice = SET_DATE_TIME;
  195. goto End;
  196. }
  197. if (lstrcmp(V_BSTR(&varValue), SET_TIME_ZONE_TASK) == 0)
  198. {
  199. sdtChoice = SET_TIME_ZONE;
  200. goto End;
  201. }
  202. if (lstrcmp(V_BSTR(&varValue), APPLIANCE_INITIALIZATION_TASK) == 0)
  203. {
  204. sdtChoice = RAISE_SETDATETIME_ALERT;
  205. goto End;
  206. }
  207. End:
  208. VariantClear(&varValue);
  209. SysFreeString(bstrParamName);
  210. if (FAILED(hr))
  211. {
  212. sdtChoice = NONE_FOUND;
  213. }
  214. return sdtChoice;
  215. }
  216. STDMETHODIMP CDateTime::GetSetDateTimeParameters(IN ITaskContext *pTaskContext,
  217. OUT SYSTEMTIME *pLocalTime)
  218. {
  219. BSTR bstrParamDateDay = SysAllocString(PARAM_DATE_DAY);
  220. BSTR bstrParamDateMonth = SysAllocString(PARAM_DATE_MONTH);
  221. BSTR bstrParamDateYear = SysAllocString(PARAM_DATE_YEAR);
  222. BSTR bstrParamTimeHour = SysAllocString(PARAM_TIME_HOUR);
  223. BSTR bstrParamTimeMinute = SysAllocString(PARAM_TIME_MINUTE);
  224. HRESULT hr;
  225. VARIANT varValue;
  226. ASSERT(pTaskContext);
  227. //
  228. // Clear the LocalTime Structure
  229. //
  230. ZeroMemory(pLocalTime, sizeof(SYSTEMTIME));
  231. //
  232. // Retrieve Day from TaskContext
  233. //
  234. VariantClear(&varValue);
  235. hr = pTaskContext->GetParameter(bstrParamDateDay,
  236. &varValue);
  237. TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
  238. %X"), PARAM_DATE_DAY, hr);
  239. if (V_VT(&varValue) != VT_BSTR)
  240. {
  241. TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
  242. in CDateTime:GetSetDateTime"), \
  243. V_VT(&varValue), PARAM_DATE_DAY);
  244. hr = E_INVALIDARG;
  245. goto End;
  246. }
  247. pLocalTime->wDay = (WORD)_ttoi(V_BSTR(&varValue));
  248. //
  249. // Retrieve Month from TaskContext
  250. //
  251. VariantClear(&varValue);
  252. hr = pTaskContext->GetParameter(bstrParamDateMonth,
  253. &varValue);
  254. TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
  255. %X"), PARAM_DATE_MONTH, hr);
  256. if (V_VT(&varValue) != VT_BSTR)
  257. {
  258. TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
  259. in CDateTime:GetSetDateTime"), \
  260. V_VT(&varValue), PARAM_DATE_MONTH);
  261. hr = E_INVALIDARG;
  262. goto End;
  263. }
  264. pLocalTime->wMonth = (WORD) _ttoi(V_BSTR(&varValue));;
  265. //
  266. // Retrieve Year from TaskContext
  267. //
  268. VariantClear(&varValue);
  269. hr = pTaskContext->GetParameter(bstrParamDateYear,
  270. &varValue);
  271. TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
  272. %X"), PARAM_DATE_YEAR, hr);
  273. if (V_VT(&varValue) != VT_BSTR)
  274. {
  275. TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
  276. in CDateTime:GetSetDateTime"), \
  277. V_VT(&varValue), PARAM_DATE_YEAR);
  278. hr = E_INVALIDARG;
  279. goto End;
  280. }
  281. pLocalTime->wYear = (WORD) _ttoi(V_BSTR(&varValue));
  282. //
  283. // Retrieve Hour from TaskContext
  284. //
  285. VariantClear(&varValue);
  286. hr = pTaskContext->GetParameter(bstrParamTimeHour,
  287. &varValue);
  288. TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
  289. %X"), PARAM_TIME_HOUR, hr);
  290. if (V_VT(&varValue) != VT_BSTR)
  291. {
  292. TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
  293. in CDateTime:GetSetDateTime"), \
  294. V_VT(&varValue), PARAM_TIME_HOUR);
  295. hr = E_INVALIDARG;
  296. goto End;
  297. }
  298. pLocalTime->wHour = (WORD) _ttoi(V_BSTR(&varValue));
  299. //
  300. // Retrieve Minute from TaskContext
  301. //
  302. VariantClear(&varValue);
  303. hr = pTaskContext->GetParameter(bstrParamTimeMinute,
  304. &varValue);
  305. TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
  306. %X"), PARAM_TIME_MINUTE, hr);
  307. if (V_VT(&varValue) != VT_BSTR)
  308. {
  309. TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
  310. in CDateTime:GetSetDateTime"), \
  311. V_VT(&varValue), PARAM_TIME_MINUTE);
  312. hr = E_INVALIDARG;
  313. goto End;
  314. }
  315. pLocalTime->wMinute = (WORD) _ttoi(V_BSTR(&varValue));
  316. hr = S_OK;
  317. End:
  318. VariantClear(&varValue);
  319. SysFreeString(bstrParamDateDay);
  320. SysFreeString(bstrParamDateMonth);
  321. SysFreeString(bstrParamDateYear);
  322. SysFreeString(bstrParamTimeHour);
  323. SysFreeString(bstrParamTimeMinute);
  324. return hr;
  325. }
  326. STDMETHODIMP CDateTime::SetDateTime(IN ITaskContext *pTaskContext)
  327. {
  328. SYSTEMTIME LocalTime;
  329. HRESULT hr;
  330. ASSERT(pTaskContext);
  331. ZeroMemory(&LocalTime, sizeof(SYSTEMTIME));
  332. hr = GetSetDateTimeParameters(pTaskContext, &LocalTime);
  333. if (S_OK != hr)
  334. {
  335. return hr;
  336. }
  337. //
  338. // Save the current date/time - in case this operation has to be rolled back
  339. //
  340. ZeroMemory(&m_OldDateTime, sizeof(SYSTEMTIME));
  341. GetLocalTime(&m_OldDateTime);
  342. //
  343. // Set the new date/time
  344. // Note that Windows NT uses the Daylight Saving Time setting of the
  345. // current time, not the new time we are setting. Therefore, calling
  346. // SetLocalTime again, now that the Daylight Saving Time setting is set
  347. // for the new time, will guarantee the correct result.
  348. //
  349. if (TRUE == SetLocalTime(&LocalTime))
  350. {
  351. if (TRUE == SetLocalTime(&LocalTime))
  352. {
  353. //
  354. // Successful set the new date/time
  355. //
  356. return S_OK;
  357. }
  358. }
  359. //
  360. // if we got here, one of the SetLocalTime calls must have failed
  361. // We should restore the time here the old time here since
  362. // we will not get called on TaskComplete method
  363. // We will lose may be a second or two - tough luck!
  364. //
  365. hr = HRESULT_FROM_WIN32(GetLastError());
  366. TRACE1(("SetDateTime failed to set the new time %X"), hr);
  367. if (TRUE == SetLocalTime(&m_OldDateTime))
  368. {
  369. if (TRUE == SetLocalTime(&m_OldDateTime))
  370. {
  371. //
  372. // Successful restored the old date/time
  373. // Return the old error code back to AppMgr, since the attempt
  374. // to set new time had failed
  375. //
  376. TRACE("SetDateTime has restored the old time");
  377. return hr;
  378. }
  379. }
  380. //
  381. // If we got here, the time to restore to old time has failed!!
  382. // There is not much we can do :-(
  383. //
  384. TRACE1(("SetDateTime failed to set restore the old time %X"), HRESULT_FROM_WIN32(GetLastError()));
  385. return hr;
  386. }
  387. STDMETHODIMP CDateTime::GetSetTimeZoneParameters(IN ITaskContext *pTaskContext,
  388. OUT LPTSTR *lpStandardTimeZoneName,
  389. OUT BOOL *pbEnableDayLightSavings)
  390. {
  391. BSTR bstrParamTimeZoneName = SysAllocString(PARAM_TIMEZONE_STANDARDTIME);
  392. BSTR bstrParamEnableDayLightSavings = SysAllocString(PARAM_DAYLIGHT_ENABLE);
  393. HRESULT hr;
  394. VARIANT varValue;
  395. LPTSTR szEnableDayLight = NULL;
  396. HANDLE hProcessHeap = NULL;
  397. ASSERT(pTaskContext);
  398. ASSERT(lpStandardTimeZoneName);
  399. ASSERT(pbEnableDayLightSavings);
  400. TRACE("Enter GetSetTimeZoneParameters");
  401. (*lpStandardTimeZoneName) = NULL;
  402. //
  403. // Retrieve Standard Time Zone name from TaskContext
  404. //
  405. VariantClear(&varValue);
  406. hr = pTaskContext->GetParameter(bstrParamTimeZoneName,
  407. &varValue);
  408. TRACE2("GetParameter %ws returned in CDateTime::GetSetTimeZoneParameters "
  409. "%X", PARAM_TIMEZONE_STANDARDTIME, hr);
  410. if (V_VT(&varValue) != VT_BSTR)
  411. {
  412. TRACE2("Non-string(%X) parameter received for %ws in GetParameter "
  413. "in CDateTime:GetSetTimeZoneParameters",
  414. V_VT(&varValue), PARAM_TIMEZONE_STANDARDTIME);
  415. hr = E_INVALIDARG;
  416. goto End;
  417. }
  418. hProcessHeap = GetProcessHeap();
  419. if (NULL == hProcessHeap)
  420. {
  421. hr = HRESULT_FROM_WIN32(GetLastError());
  422. goto End;
  423. }
  424. *lpStandardTimeZoneName = (LPTSTR) HeapAlloc(hProcessHeap, 0,
  425. ((lstrlen(V_BSTR(&varValue)) + 1) * sizeof(TCHAR)));
  426. if (NULL == *lpStandardTimeZoneName)
  427. {
  428. hr = HRESULT_FROM_WIN32(GetLastError());
  429. goto End;
  430. }
  431. lstrcpy(*lpStandardTimeZoneName, V_BSTR(&varValue));
  432. //
  433. // Retrieve EnableDayLightSavings flag from TaskContext
  434. //
  435. VariantClear(&varValue);
  436. hr = pTaskContext->GetParameter(bstrParamEnableDayLightSavings,
  437. &varValue);
  438. TRACE2(("GetParameter %ws returned in CDateTime::GetSetTimeZoneParameters\
  439. %X"), PARAM_DAYLIGHT_ENABLE, hr);
  440. if (V_VT(&varValue) != VT_BSTR)
  441. {
  442. TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
  443. in CDateTime:GetSetTimeZoneParameters"), \
  444. V_VT(&varValue), PARAM_DAYLIGHT_ENABLE);
  445. hr = E_INVALIDARG;
  446. goto End;
  447. }
  448. //
  449. // TODO: Convert String value to WORD
  450. //
  451. szEnableDayLight = V_BSTR(&varValue);
  452. *pbEnableDayLightSavings = ((szEnableDayLight[0] == L'y') || (szEnableDayLight[0] == L'Y')) ? TRUE : FALSE;
  453. hr = S_OK;
  454. End:
  455. VariantClear(&varValue);
  456. SysFreeString(bstrParamTimeZoneName);
  457. SysFreeString(bstrParamEnableDayLightSavings);
  458. if (S_OK != hr)
  459. {
  460. if (NULL != *lpStandardTimeZoneName)
  461. {
  462. HeapFree(hProcessHeap, 0, *lpStandardTimeZoneName);
  463. *lpStandardTimeZoneName = NULL;
  464. }
  465. }
  466. TRACE1("Leave GetSetTimeZoneParameters, %x", hr);
  467. return hr;
  468. }
  469. STDMETHODIMP CDateTime::SetTimeZone(IN ITaskContext *pTaskContext)
  470. {
  471. BOOL bEnableDayLightSaving;
  472. LPTSTR lpTimeZoneStandardName = NULL;
  473. HRESULT hr;
  474. PTZINFO pTimeZoneInfoList = NULL;
  475. PTZINFO pTimeZone = NULL;
  476. int iCount;
  477. ASSERT(pTaskContext);
  478. TRACE("Enter SetTimeZone");
  479. hr = GetSetTimeZoneParameters(pTaskContext,
  480. &lpTimeZoneStandardName,
  481. &bEnableDayLightSaving);
  482. if (S_OK != hr)
  483. {
  484. goto CleanupAndExit;
  485. }
  486. //
  487. // Save the current timezone information - in case this operation
  488. // has to be rolled back
  489. //
  490. ZeroMemory(&m_OldTimeZoneInformation, sizeof(TIME_ZONE_INFORMATION));
  491. GetTimeZoneInformation(&m_OldTimeZoneInformation);
  492. m_OldEnableDayLightSaving = GetAllowLocalTimeChange();
  493. //
  494. // Read the list of possible timezones from the registry
  495. //
  496. iCount = ReadTimezones(&pTimeZoneInfoList);
  497. if (0 >= iCount)
  498. {
  499. hr = E_FAIL;
  500. TRACE1(("SetTimeZone failed to enumerate time zones %X"), hr);
  501. goto CleanupAndExit;
  502. }
  503. //
  504. // Search for the specified Time Zone
  505. //
  506. for (pTimeZone = pTimeZoneInfoList; pTimeZone; pTimeZone = pTimeZone->next)
  507. {
  508. if (0 == lstrcmpi(pTimeZone->szStandardName, lpTimeZoneStandardName))
  509. {
  510. break;
  511. }
  512. }
  513. if (NULL != pTimeZone)
  514. {
  515. SetTheTimezone(bEnableDayLightSaving, pTimeZone);
  516. hr = S_OK;
  517. }
  518. else
  519. {
  520. //
  521. // if we got here, there were no matches for the input Time Zone
  522. //
  523. hr = E_FAIL;
  524. TRACE1(("SetDateTime:: There were no TimeZone matching the input %X"), hr);
  525. }
  526. CleanupAndExit:
  527. if (NULL != lpTimeZoneStandardName)
  528. {
  529. HeapFree(GetProcessHeap(), 0, lpTimeZoneStandardName);
  530. }
  531. FreeTimezoneList(&pTimeZoneInfoList);
  532. TRACE1("Leave SetTimeZone, %x", hr);
  533. return hr;
  534. }
  535. STDMETHODIMP CDateTime::RollbackSetTimeZone(IN ITaskContext *pTaskContext)
  536. {
  537. HRESULT hr = S_OK;
  538. ASSERT(pTaskContext);
  539. //
  540. // Set the Time Zone and Enable Daylight savings to previous values
  541. //
  542. if (FALSE == SetTimeZoneInformation(&m_OldTimeZoneInformation))
  543. {
  544. //
  545. // There is not much we can do !!
  546. //
  547. hr = HRESULT_FROM_WIN32(GetLastError());
  548. }
  549. SetAllowLocalTimeChange(m_OldEnableDayLightSaving);
  550. return hr;
  551. }
  552. STDMETHODIMP CDateTime::RollbackSetDateTime(IN ITaskContext *pTaskContext)
  553. {
  554. HRESULT hr = S_OK;
  555. ASSERT(pTaskContext);
  556. //
  557. // Set the Date/Time to previous values
  558. // We could have lost sometime in between - but this is the best we can do
  559. //
  560. //
  561. // Note that Windows NT uses the Daylight Saving Time setting of the
  562. // current time, not the new time we are setting. Therefore, calling
  563. // SetLocalTime again, now that the Daylight Saving Time setting is set
  564. // for the new time, will guarantee the correct result.
  565. //
  566. if (TRUE == SetLocalTime(&m_OldDateTime))
  567. {
  568. if (TRUE == SetLocalTime(&m_OldDateTime))
  569. {
  570. //
  571. // Success
  572. //
  573. return S_OK;
  574. }
  575. }
  576. //
  577. // If we got here, the SetLocalTime call(s) must have failed
  578. // Unfortunately, there is not much we can do !!
  579. //
  580. hr = HRESULT_FROM_WIN32(GetLastError());
  581. return hr;
  582. }
  583. ////////////////////////////////////////////////////////////////////////////
  584. //
  585. // ReadZoneData
  586. //
  587. // Reads the data for a time zone from the registry.
  588. //
  589. ////////////////////////////////////////////////////////////////////////////
  590. BOOL CDateTime::ReadZoneData(PTZINFO zone, HKEY key, LPCTSTR keyname)
  591. {
  592. DWORD len;
  593. len = sizeof(zone->szDisplayName);
  594. if (RegQueryValueEx(key,
  595. c_szTZDisplayName,
  596. 0,
  597. NULL,
  598. (LPBYTE)zone->szDisplayName,
  599. &len ) != ERROR_SUCCESS)
  600. {
  601. return (FALSE);
  602. }
  603. //
  604. // Under NT, the keyname is the "Standard" name. Values stored
  605. // under the keyname contain the other strings and binary info
  606. // related to the time zone. Every time zone must have a standard
  607. // name, therefore, we save registry space by using the Standard
  608. // name as the subkey name under the "Time Zones" key.
  609. //
  610. len = sizeof(zone->szStandardName);
  611. if (RegQueryValueEx(key,
  612. c_szTZStandardName,
  613. 0,
  614. NULL,
  615. (LPBYTE)zone->szStandardName,
  616. &len ) != ERROR_SUCCESS)
  617. {
  618. //
  619. // Use keyname if can't get StandardName value.
  620. //
  621. lstrcpyn(zone->szStandardName,
  622. keyname,
  623. sizeof(zone->szStandardName) );
  624. }
  625. len = sizeof(zone->szDaylightName);
  626. if (RegQueryValueEx(key,
  627. c_szTZDaylightName,
  628. 0,
  629. NULL,
  630. (LPBYTE)zone->szDaylightName,
  631. &len ) != ERROR_SUCCESS)
  632. {
  633. return (FALSE);
  634. }
  635. len = sizeof(zone->Bias) +
  636. sizeof(zone->StandardBias) +
  637. sizeof(zone->DaylightBias) +
  638. sizeof(zone->StandardDate) +
  639. sizeof(zone->DaylightDate);
  640. if (RegQueryValueEx(key,
  641. c_szTZI,
  642. 0,
  643. NULL,
  644. (LPBYTE)&zone->Bias,
  645. &len ) != ERROR_SUCCESS)
  646. {
  647. return (FALSE);
  648. }
  649. return (TRUE);
  650. }
  651. ////////////////////////////////////////////////////////////////////////////
  652. //
  653. // AddZoneToList
  654. //
  655. // Inserts a new time zone into a list, sorted by bias and then name.
  656. //
  657. ////////////////////////////////////////////////////////////////////////////
  658. void CDateTime::AddZoneToList(PTZINFO *list,
  659. PTZINFO zone)
  660. {
  661. if (*list)
  662. {
  663. PTZINFO curr = *list;
  664. PTZINFO next = NULL;
  665. //
  666. // Go to end of the list
  667. //
  668. while (curr && curr->next)
  669. {
  670. curr = curr->next;
  671. next = curr->next;
  672. }
  673. if (curr)
  674. {
  675. curr->next = zone;
  676. }
  677. if (zone)
  678. {
  679. zone->next = NULL;
  680. }
  681. }
  682. else
  683. {
  684. *list = zone;
  685. }
  686. }
  687. ////////////////////////////////////////////////////////////////////////////
  688. //
  689. // FreeTimezoneList
  690. //
  691. // Frees all time zones in the passed list, setting the head to NULL.
  692. //
  693. ////////////////////////////////////////////////////////////////////////////
  694. void CDateTime::FreeTimezoneList(PTZINFO *list)
  695. {
  696. while (*list)
  697. {
  698. PTZINFO next = (*list)->next;
  699. LocalFree((HANDLE)*list);
  700. *list = next;
  701. }
  702. }
  703. ////////////////////////////////////////////////////////////////////////////
  704. //
  705. // ReadTimezones
  706. //
  707. // Reads the time zone information from the registry.
  708. // Returns num read, -1 on failure.
  709. //
  710. ////////////////////////////////////////////////////////////////////////////
  711. int CDateTime::ReadTimezones(PTZINFO *list)
  712. {
  713. HKEY key = NULL;
  714. int count = -1;
  715. *list = NULL;
  716. if (RegOpenKey( HKEY_LOCAL_MACHINE,
  717. c_szTimeZones,
  718. &key ) == ERROR_SUCCESS)
  719. {
  720. TCHAR name[TZNAME_SIZE];
  721. PTZINFO zone = NULL;
  722. int i;
  723. count = 0;
  724. for (i = 0;
  725. RegEnumKey(key, i, name, TZNAME_SIZE) == ERROR_SUCCESS;
  726. i++)
  727. {
  728. HKEY subkey = NULL;
  729. if (!zone &&
  730. ((zone = (PTZINFO)LocalAlloc(LPTR, sizeof(TZINFO))) == NULL))
  731. {
  732. zone = *list;
  733. *list = NULL;
  734. count = -1;
  735. break;
  736. }
  737. zone->next = NULL;
  738. if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS)
  739. {
  740. //
  741. // Each sub key name under the Time Zones key is the
  742. // "Standard" name for the Time Zone.
  743. //
  744. lstrcpyn(zone->szStandardName, name, TZNAME_SIZE);
  745. if (ReadZoneData(zone, subkey, name))
  746. {
  747. AddZoneToList(list, zone);
  748. zone = NULL;
  749. count++;
  750. }
  751. RegCloseKey(subkey);
  752. }
  753. }
  754. FreeTimezoneList(&zone);
  755. RegCloseKey(key);
  756. }
  757. return (count);
  758. }
  759. ////////////////////////////////////////////////////////////////////////////
  760. //
  761. // GetAllowLocalTimeChange
  762. //
  763. ////////////////////////////////////////////////////////////////////////////
  764. TCHAR c_szRegPathTZControl[] = REGSTR_PATH_TIMEZONE;
  765. TCHAR c_szRegValDisableTZUpdate[] = REGSTR_VAL_TZNOAUTOTIME;
  766. BOOL CDateTime::GetAllowLocalTimeChange(void)
  767. {
  768. //
  769. // Assume allowed until we see a disallow flag.
  770. //
  771. BOOL result = TRUE;
  772. HKEY key;
  773. if (RegOpenKey( HKEY_LOCAL_MACHINE,
  774. c_szRegPathTZControl,
  775. &key ) == ERROR_SUCCESS)
  776. {
  777. //
  778. // Assume no disallow flag until we see one.
  779. //
  780. DWORD value = 0;
  781. DWORD dwlen = sizeof(value);
  782. DWORD type;
  783. if ((RegQueryValueEx( key,
  784. c_szRegValDisableTZUpdate,
  785. NULL,
  786. &type,
  787. (LPBYTE)&value,
  788. &dwlen ) == ERROR_SUCCESS) &&
  789. ((type == REG_DWORD) || (type == REG_BINARY)) &&
  790. (dwlen == sizeof(value)) && value)
  791. {
  792. //
  793. // Okay, we have a nonzero value, it is either:
  794. //
  795. // 1) 0xFFFFFFFF
  796. // this is set in an inf file for first boot to prevent
  797. // the base from performing any cutovers during setup.
  798. //
  799. // 2) some other value
  800. // this signifies that the user actualy disabled cutovers
  801. // *return that local time changes are disabled
  802. //
  803. if (value != 0xFFFFFFFF)
  804. {
  805. result = FALSE;
  806. }
  807. }
  808. RegCloseKey(key);
  809. }
  810. return (result);
  811. }
  812. ////////////////////////////////////////////////////////////////////////////
  813. //
  814. // SetAllowLocalTimeChange
  815. //
  816. ////////////////////////////////////////////////////////////////////////////
  817. void CDateTime::SetAllowLocalTimeChange(BOOL fAllow)
  818. {
  819. HKEY key = NULL;
  820. if (fAllow)
  821. {
  822. //
  823. // Remove the disallow flag from the registry if it exists.
  824. //
  825. if (RegOpenKey( HKEY_LOCAL_MACHINE,
  826. c_szRegPathTZControl,
  827. &key ) == ERROR_SUCCESS)
  828. {
  829. RegDeleteValue(key, c_szRegValDisableTZUpdate);
  830. }
  831. }
  832. else
  833. {
  834. //
  835. // Add/set the nonzero disallow flag.
  836. //
  837. if (RegCreateKey( HKEY_LOCAL_MACHINE,
  838. c_szRegPathTZControl,
  839. &key ) == ERROR_SUCCESS)
  840. {
  841. DWORD value = 1;
  842. RegSetValueEx( key,
  843. (LPCTSTR)c_szRegValDisableTZUpdate,
  844. 0UL,
  845. REG_DWORD,
  846. (LPBYTE)&value,
  847. sizeof(value) );
  848. }
  849. }
  850. if (key)
  851. {
  852. RegCloseKey(key);
  853. }
  854. }
  855. ////////////////////////////////////////////////////////////////////////////
  856. //
  857. // SetTheTimezone
  858. //
  859. // Apply the time zone selection.
  860. //
  861. ////////////////////////////////////////////////////////////////////////////
  862. void CDateTime::SetTheTimezone(BOOL bAutoMagicTimeChange, PTZINFO ptzi)
  863. {
  864. TIME_ZONE_INFORMATION tzi;
  865. if (!ptzi)
  866. {
  867. return;
  868. }
  869. tzi.Bias = ptzi->Bias;
  870. if ((bAutoMagicTimeChange == 0) ||
  871. (ptzi->StandardDate.wMonth == 0))
  872. {
  873. //
  874. // Standard Only.
  875. //
  876. tzi.StandardBias = ptzi->StandardBias;
  877. tzi.DaylightBias = ptzi->StandardBias;
  878. tzi.StandardDate = ptzi->StandardDate;
  879. tzi.DaylightDate = ptzi->StandardDate;
  880. lstrcpy(tzi.StandardName, ptzi->szStandardName);
  881. lstrcpy(tzi.DaylightName, ptzi->szStandardName);
  882. }
  883. else
  884. {
  885. //
  886. // Automatically adjust for Daylight Saving Time.
  887. //
  888. tzi.StandardBias = ptzi->StandardBias;
  889. tzi.DaylightBias = ptzi->DaylightBias;
  890. tzi.StandardDate = ptzi->StandardDate;
  891. tzi.DaylightDate = ptzi->DaylightDate;
  892. lstrcpy(tzi.StandardName, ptzi->szStandardName);
  893. lstrcpy(tzi.DaylightName, ptzi->szDaylightName);
  894. }
  895. SetAllowLocalTimeChange(bAutoMagicTimeChange);
  896. SetTimeZoneInformation(&tzi);
  897. }
  898. STDMETHODIMP CDateTime::RaiseSetDateTimeAlert(void)
  899. {
  900. CComPtr<IApplianceServices> pAppSrvcs = NULL;
  901. DWORD dwAlertType = SA_ALERT_TYPE_ATTENTION;
  902. DWORD dwAlertId = SA_DATETIME_NOT_CONFIGURED_ALERT;
  903. HRESULT hr = E_FAIL;
  904. _bstr_t bstrAlertLog(ALERT_LOG_NAME);
  905. _bstr_t bstrAlertSource(ALERT_SOURCE);
  906. _variant_t varReplacementStrings;
  907. _variant_t varRawData;
  908. LONG lCookie;
  909. SATraceFunction("RaiseSetDateTimeAlert");
  910. hr = CoCreateInstance(CLSID_ApplianceServices,
  911. NULL,
  912. CLSCTX_INPROC_SERVER ,
  913. IID_IApplianceServices,
  914. (void**)&pAppSrvcs);
  915. if (FAILED(hr))
  916. {
  917. ASSERTMSG(FALSE, L"RaiseSetDateTimeAlert failed at CoCreateInstance");
  918. TRACE1("RaiseSetDateTimeAlert failed at CoCreateInstance, %x", hr);
  919. goto End;
  920. }
  921. ASSERT(pAppSrvcs);
  922. hr = pAppSrvcs->Initialize();
  923. if (FAILED(hr))
  924. {
  925. ASSERTMSG(FALSE, L"RaiseSetDateTimeAlert failed at pAppSrvcs->Initialize");
  926. TRACE1("RaiseSetDateTimeAlert failed at pAppSrvcs->Initialize, %x", hr);
  927. goto End;
  928. }
  929. hr = pAppSrvcs->RaiseAlert(dwAlertType,
  930. dwAlertId,
  931. bstrAlertLog,
  932. bstrAlertSource,
  933. SA_ALERT_DURATION_ETERNAL,
  934. &varReplacementStrings,
  935. &varRawData,
  936. &lCookie);
  937. if (FAILED(hr))
  938. {
  939. ASSERTMSG(FALSE, TEXT("RaiseSetDateTimeAlert failed at pAppSrvcs->RaiseAlert"));
  940. TRACE1("RaiseSetDateTimeAlert failed at pAppSrvcs->RaiseAlert, %x", hr);
  941. }
  942. End:
  943. return hr;
  944. }
  945. BOOL CDateTime::DoNotRaiseDateTimeAlert(void)
  946. {
  947. LONG lReturnValue;
  948. HKEY hKey = NULL;
  949. DWORD dwDisposition, dwRaiseDateTimeAlert = 0;
  950. BOOL bReturnCode = FALSE;
  951. SATraceFunction("DoNotRaiseDateTimeAlert");
  952. //
  953. // Write Settings to registry
  954. //
  955. lReturnValue = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  956. REGKEY_SA_DATETIME,
  957. 0,
  958. NULL,
  959. REG_OPTION_NON_VOLATILE,
  960. KEY_ALL_ACCESS,
  961. NULL,
  962. &hKey,
  963. &dwDisposition);
  964. if (lReturnValue != ERROR_SUCCESS)
  965. {
  966. TRACE1("RegCreateKeyEx failed with %X", lReturnValue);
  967. goto End;
  968. }
  969. //
  970. // Set RaiseAlert value to 0
  971. //
  972. dwRaiseDateTimeAlert = 0;
  973. lReturnValue = RegSetValueEx(hKey,
  974. REGSTR_VAL_DATETIME_RAISEALERT,
  975. 0,
  976. REG_DWORD,
  977. (LPBYTE) &dwRaiseDateTimeAlert,
  978. sizeof(DWORD));
  979. if (lReturnValue != ERROR_SUCCESS)
  980. {
  981. TRACE2("RegSetValueEx of %ws failed with %X", REGSTR_VAL_DATETIME_RAISEALERT, lReturnValue);
  982. goto End;
  983. }
  984. else
  985. {
  986. bReturnCode = TRUE;
  987. }
  988. End:
  989. if (NULL != hKey)
  990. {
  991. RegCloseKey(hKey);
  992. }
  993. return bReturnCode;
  994. }
  995. BOOL CDateTime::ShouldRaiseDateTimeAlert(void)
  996. {
  997. LONG lReturnValue;
  998. HKEY hKey = NULL;
  999. DWORD dwSize, dwType, dwRaiseDateTimeAlert = 0;
  1000. BOOL bReturnCode = TRUE;
  1001. SATraceFunction("ShouldRaiseDateTimeAlert");
  1002. //
  1003. // Open HKLM\Software\Microsoft\ServerAppliance\DateTime reg key
  1004. //
  1005. lReturnValue = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1006. REGKEY_SA_DATETIME,
  1007. 0,
  1008. KEY_READ,
  1009. &hKey);
  1010. if (lReturnValue != ERROR_SUCCESS)
  1011. {
  1012. TRACE1("RegOpenKeyEx failed with %X", lReturnValue);
  1013. goto End;
  1014. }
  1015. //
  1016. // Read the RaiseAlert reg key
  1017. //
  1018. dwSize = sizeof(DWORD);
  1019. lReturnValue = RegQueryValueEx(hKey,
  1020. REGSTR_VAL_DATETIME_RAISEALERT,
  1021. 0,
  1022. &dwType,
  1023. (LPBYTE) &dwRaiseDateTimeAlert,
  1024. &dwSize);
  1025. if (lReturnValue != ERROR_SUCCESS)
  1026. {
  1027. TRACE2("RegQueryValueEx of %ws failed with %X", REGSTR_VAL_DATETIME_RAISEALERT, lReturnValue);
  1028. goto End;
  1029. }
  1030. if (0 == dwRaiseDateTimeAlert)
  1031. {
  1032. bReturnCode = FALSE;
  1033. }
  1034. End:
  1035. if (NULL != hKey)
  1036. {
  1037. RegCloseKey(hKey);
  1038. }
  1039. return bReturnCode;
  1040. }
  1041. BOOL CDateTime::ClearDateTimeAlert(void)
  1042. {
  1043. CComPtr<IApplianceServices> pAppSrvcs = NULL;
  1044. HRESULT hr = E_FAIL;
  1045. _bstr_t bstrAlertLog(ALERT_LOG_NAME);
  1046. BOOL bReturnCode = FALSE;
  1047. SATraceFunction("ClearDateTimeAlert");
  1048. hr = CoCreateInstance(CLSID_ApplianceServices,
  1049. NULL,
  1050. CLSCTX_INPROC_SERVER ,
  1051. IID_IApplianceServices,
  1052. (void**)&pAppSrvcs);
  1053. if (FAILED(hr))
  1054. {
  1055. ASSERTMSG(FALSE, L"ClearDateTimeAlert failed at CoCreateInstance");
  1056. TRACE1("ClearDateTimeAlert failed at CoCreateInstance, %x", hr);
  1057. goto End;
  1058. }
  1059. ASSERT(pAppSrvcs);
  1060. hr = pAppSrvcs->Initialize();
  1061. if (FAILED(hr))
  1062. {
  1063. ASSERTMSG(FALSE, L"ClearDateTimeAlert failed at pAppSrvcs->Initialize");
  1064. TRACE1("ClearDateTimeAlert failed at pAppSrvcs->Initialize, %x", hr);
  1065. goto End;
  1066. }
  1067. hr = pAppSrvcs->ClearAlertAll(SA_DATETIME_NOT_CONFIGURED_ALERT,
  1068. bstrAlertLog);
  1069. //
  1070. // DISP_E_MEMBERNOTFOUND means that there were no matching alerts
  1071. //
  1072. if ((hr != DISP_E_MEMBERNOTFOUND) && (FAILED(hr)))
  1073. {
  1074. ASSERTMSG(FALSE, TEXT("ClearDateTimeAlert failed at pAppSrvcs->RaiseAlert"));
  1075. TRACE1("ClearDateTimeAlert failed at pAppSrvcs->RaiseAlert, %x", hr);
  1076. }
  1077. else
  1078. {
  1079. bReturnCode = TRUE;
  1080. }
  1081. End:
  1082. return bReturnCode;
  1083. }