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
1368 lines
37 KiB
// DateTime.cpp : Implementation of CDateTime
|
|
#include "stdafx.h"
|
|
#include <regstr.h>
|
|
#include <comdef.h>
|
|
#include <comutil.h>
|
|
#include "SetDateTime.h"
|
|
#include "debug.h"
|
|
|
|
#include "appliancetask.h"
|
|
#include "taskctx.h"
|
|
#include "DateTime.h"
|
|
|
|
|
|
#include "appsrvcs.h"
|
|
#include "appmgrobjs.h"
|
|
#include "..\datetimemsg\datetimemsg.h"
|
|
|
|
//
|
|
// Registry location for Time Zone information.
|
|
//
|
|
TCHAR c_szTimeZones[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
|
|
|
|
//
|
|
// Time Zone data value keys.
|
|
//
|
|
TCHAR c_szTZDisplayName[] = TEXT("Display");
|
|
TCHAR c_szTZStandardName[] = TEXT("Std");
|
|
TCHAR c_szTZDaylightName[] = TEXT("Dlt");
|
|
TCHAR c_szTZI[] = TEXT("TZI");
|
|
|
|
|
|
|
|
#define PARAM_DATE_DAY TEXT("Day")
|
|
#define PARAM_DATE_MONTH TEXT("Month")
|
|
#define PARAM_DATE_YEAR TEXT("Year")
|
|
#define PARAM_TIME_HOUR TEXT("Hour")
|
|
#define PARAM_TIME_MINUTE TEXT("Minute")
|
|
#define PARAM_TIMEZONE_STANDARDTIME TEXT("StandardName")
|
|
#define PARAM_DAYLIGHT_ENABLE TEXT("EnableDayLight")
|
|
|
|
#define ALERT_LOG_NAME TEXT("MSSAKitComm")
|
|
#define ALERT_SOURCE TEXT("")
|
|
#define REGKEY_SA_DATETIME TEXT("Software\\Microsoft\\ServerAppliance\\DateTime")
|
|
#define REGSTR_VAL_DATETIME_RAISEALERT TEXT("RaiseAlert")
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDateTime
|
|
|
|
STDMETHODIMP CDateTime::OnTaskExecute(IUnknown *pTaskContext)
|
|
{
|
|
HRESULT hr;
|
|
ITaskContext *pTaskParameters = NULL;
|
|
SET_DATE_TIME_TASK_TYPE sdtChoice;
|
|
|
|
ASSERT(pTaskContext);
|
|
|
|
TRACE(("CDateTime::OnTaskExecute"));
|
|
|
|
hr = pTaskContext->QueryInterface(IID_ITaskContext,
|
|
(void **)&pTaskParameters);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check which Task is being executed and call that method
|
|
//
|
|
sdtChoice = GetMethodName(pTaskParameters);
|
|
switch (sdtChoice)
|
|
{
|
|
case SET_DATE_TIME:
|
|
hr = SetDateTime(pTaskParameters);
|
|
TRACE1(("SetDateTime returned %X"), hr);
|
|
break;
|
|
|
|
case SET_TIME_ZONE:
|
|
hr = SetTimeZone(pTaskParameters);
|
|
TRACE1(("SetTimeZone returned %X"), hr);
|
|
break;
|
|
|
|
case RAISE_SETDATETIME_ALERT:
|
|
//
|
|
// Alert will be raised on OnTaskComplete
|
|
//
|
|
hr = S_OK;
|
|
TRACE(("RaiseSetDateTimeAlert method called"));
|
|
break;
|
|
|
|
default:
|
|
TRACE(("GetMethodName() failed to get method name in OnTaskExecute"));
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
|
|
pTaskParameters->Release();
|
|
TRACE1("CDateTime::OnTaskExecute returning %X", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::OnTaskComplete(IUnknown *pTaskContext, LONG lTaskResult)
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
ITaskContext *pTaskParameters = NULL;
|
|
SET_DATE_TIME_TASK_TYPE sdtChoice;
|
|
|
|
ASSERT(pTaskContext);
|
|
|
|
TRACE(("CDateTime::OnTaskComplete"));
|
|
|
|
|
|
hr = pTaskContext->QueryInterface(IID_ITaskContext,
|
|
(void **)&pTaskParameters);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check which Task is being executed and call that method
|
|
//
|
|
sdtChoice = GetMethodName(pTaskParameters);
|
|
switch (sdtChoice)
|
|
{
|
|
case SET_DATE_TIME:
|
|
if (lTaskResult == SA_TASK_RESULT_COMMIT)
|
|
{
|
|
//
|
|
// Clear any existing DateTime alert and
|
|
// do not raise the datetime alert on subsequent boots
|
|
//
|
|
ClearDateTimeAlert();
|
|
DoNotRaiseDateTimeAlert();
|
|
TRACE("No rollback in OnTaskComplete");
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = RollbackSetDateTime(pTaskParameters);
|
|
TRACE1(("RollbackSetDateTime returned %X"), hr);
|
|
}
|
|
break;
|
|
|
|
|
|
case SET_TIME_ZONE:
|
|
if (lTaskResult == SA_TASK_RESULT_COMMIT)
|
|
{
|
|
//
|
|
// Clear any existing DateTime alert and
|
|
// do not raise the datetime alert on subsequent boots
|
|
//
|
|
ClearDateTimeAlert();
|
|
DoNotRaiseDateTimeAlert();
|
|
TRACE("No rollback in OnTaskComplete");
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = RollbackSetTimeZone(pTaskParameters);
|
|
TRACE1(("RollbackSetTimeZone returned %X"), hr);
|
|
}
|
|
break;
|
|
|
|
|
|
case RAISE_SETDATETIME_ALERT:
|
|
if (lTaskResult == SA_TASK_RESULT_COMMIT)
|
|
{
|
|
if (TRUE == ShouldRaiseDateTimeAlert())
|
|
{
|
|
hr = RaiseSetDateTimeAlert();
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE1(("RaiseSetDateTimeAlert returned %X"), hr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE("No need to raise the datetime alert");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do nothing on Commit failure
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
TRACE(("GetMethodName() failed to get method name in OnTaskComplete"));
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
|
|
pTaskParameters->Release();
|
|
TRACE1("CDateTime::OnTaskComplete returning %X", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Cut-n-paste from User Management code
|
|
//
|
|
SET_DATE_TIME_TASK_TYPE CDateTime::GetMethodName(IN ITaskContext *pTaskParameter)
|
|
{
|
|
BSTR bstrParamName = SysAllocString(TEXT("MethodName"));
|
|
HRESULT hr;
|
|
VARIANT varValue;
|
|
SET_DATE_TIME_TASK_TYPE sdtChoice = NONE_FOUND;
|
|
|
|
|
|
ASSERT(pTaskParameter);
|
|
|
|
|
|
hr = pTaskParameter->GetParameter(bstrParamName,
|
|
&varValue);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
TRACE1(("GetParameter failed in CDateTime::GetMethodName %X"),
|
|
hr);
|
|
}
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE1(("Non-strint(%X) parameter received in GetParameter in CSAUserTasks::GetMethodName"), V_VT(&varValue));
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
|
|
if (lstrcmp(V_BSTR(&varValue), SET_DATE_TIME_TASK) == 0)
|
|
{
|
|
sdtChoice = SET_DATE_TIME;
|
|
goto End;
|
|
}
|
|
|
|
if (lstrcmp(V_BSTR(&varValue), SET_TIME_ZONE_TASK) == 0)
|
|
{
|
|
sdtChoice = SET_TIME_ZONE;
|
|
goto End;
|
|
}
|
|
|
|
if (lstrcmp(V_BSTR(&varValue), APPLIANCE_INITIALIZATION_TASK) == 0)
|
|
{
|
|
sdtChoice = RAISE_SETDATETIME_ALERT;
|
|
goto End;
|
|
}
|
|
|
|
|
|
End:
|
|
VariantClear(&varValue);
|
|
SysFreeString(bstrParamName);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
sdtChoice = NONE_FOUND;
|
|
}
|
|
|
|
return sdtChoice;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::GetSetDateTimeParameters(IN ITaskContext *pTaskContext,
|
|
OUT SYSTEMTIME *pLocalTime)
|
|
{
|
|
BSTR bstrParamDateDay = SysAllocString(PARAM_DATE_DAY);
|
|
BSTR bstrParamDateMonth = SysAllocString(PARAM_DATE_MONTH);
|
|
BSTR bstrParamDateYear = SysAllocString(PARAM_DATE_YEAR);
|
|
BSTR bstrParamTimeHour = SysAllocString(PARAM_TIME_HOUR);
|
|
BSTR bstrParamTimeMinute = SysAllocString(PARAM_TIME_MINUTE);
|
|
HRESULT hr;
|
|
VARIANT varValue;
|
|
|
|
|
|
ASSERT(pTaskContext);
|
|
|
|
|
|
//
|
|
// Clear the LocalTime Structure
|
|
//
|
|
ZeroMemory(pLocalTime, sizeof(SYSTEMTIME));
|
|
|
|
|
|
//
|
|
// Retrieve Day from TaskContext
|
|
//
|
|
VariantClear(&varValue);
|
|
hr = pTaskContext->GetParameter(bstrParamDateDay,
|
|
&varValue);
|
|
TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
|
|
%X"), PARAM_DATE_DAY, hr);
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
|
|
in CDateTime:GetSetDateTime"), \
|
|
V_VT(&varValue), PARAM_DATE_DAY);
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
pLocalTime->wDay = (WORD)_ttoi(V_BSTR(&varValue));
|
|
|
|
|
|
//
|
|
// Retrieve Month from TaskContext
|
|
//
|
|
VariantClear(&varValue);
|
|
hr = pTaskContext->GetParameter(bstrParamDateMonth,
|
|
&varValue);
|
|
TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
|
|
%X"), PARAM_DATE_MONTH, hr);
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
|
|
in CDateTime:GetSetDateTime"), \
|
|
V_VT(&varValue), PARAM_DATE_MONTH);
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
pLocalTime->wMonth = (WORD) _ttoi(V_BSTR(&varValue));;
|
|
|
|
|
|
//
|
|
// Retrieve Year from TaskContext
|
|
//
|
|
VariantClear(&varValue);
|
|
hr = pTaskContext->GetParameter(bstrParamDateYear,
|
|
&varValue);
|
|
TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
|
|
%X"), PARAM_DATE_YEAR, hr);
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
|
|
in CDateTime:GetSetDateTime"), \
|
|
V_VT(&varValue), PARAM_DATE_YEAR);
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
pLocalTime->wYear = (WORD) _ttoi(V_BSTR(&varValue));
|
|
|
|
|
|
|
|
//
|
|
// Retrieve Hour from TaskContext
|
|
//
|
|
VariantClear(&varValue);
|
|
hr = pTaskContext->GetParameter(bstrParamTimeHour,
|
|
&varValue);
|
|
TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
|
|
%X"), PARAM_TIME_HOUR, hr);
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
|
|
in CDateTime:GetSetDateTime"), \
|
|
V_VT(&varValue), PARAM_TIME_HOUR);
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
pLocalTime->wHour = (WORD) _ttoi(V_BSTR(&varValue));
|
|
|
|
|
|
//
|
|
// Retrieve Minute from TaskContext
|
|
//
|
|
VariantClear(&varValue);
|
|
hr = pTaskContext->GetParameter(bstrParamTimeMinute,
|
|
&varValue);
|
|
TRACE2(("GetParameter %ws returned in CDateTime::GetSetDateTimeParameters\
|
|
%X"), PARAM_TIME_MINUTE, hr);
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
|
|
in CDateTime:GetSetDateTime"), \
|
|
V_VT(&varValue), PARAM_TIME_MINUTE);
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
pLocalTime->wMinute = (WORD) _ttoi(V_BSTR(&varValue));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
End:
|
|
VariantClear(&varValue);
|
|
SysFreeString(bstrParamDateDay);
|
|
SysFreeString(bstrParamDateMonth);
|
|
SysFreeString(bstrParamDateYear);
|
|
SysFreeString(bstrParamTimeHour);
|
|
SysFreeString(bstrParamTimeMinute);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::SetDateTime(IN ITaskContext *pTaskContext)
|
|
{
|
|
SYSTEMTIME LocalTime;
|
|
HRESULT hr;
|
|
|
|
ASSERT(pTaskContext);
|
|
|
|
|
|
ZeroMemory(&LocalTime, sizeof(SYSTEMTIME));
|
|
|
|
|
|
hr = GetSetDateTimeParameters(pTaskContext, &LocalTime);
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Save the current date/time - in case this operation has to be rolled back
|
|
//
|
|
ZeroMemory(&m_OldDateTime, sizeof(SYSTEMTIME));
|
|
GetLocalTime(&m_OldDateTime);
|
|
|
|
//
|
|
// Set the new date/time
|
|
// Note that Windows NT uses the Daylight Saving Time setting of the
|
|
// current time, not the new time we are setting. Therefore, calling
|
|
// SetLocalTime again, now that the Daylight Saving Time setting is set
|
|
// for the new time, will guarantee the correct result.
|
|
//
|
|
if (TRUE == SetLocalTime(&LocalTime))
|
|
{
|
|
if (TRUE == SetLocalTime(&LocalTime))
|
|
{
|
|
//
|
|
// Successful set the new date/time
|
|
//
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// if we got here, one of the SetLocalTime calls must have failed
|
|
// We should restore the time here the old time here since
|
|
// we will not get called on TaskComplete method
|
|
// We will lose may be a second or two - tough luck!
|
|
//
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
TRACE1(("SetDateTime failed to set the new time %X"), hr);
|
|
|
|
|
|
if (TRUE == SetLocalTime(&m_OldDateTime))
|
|
{
|
|
if (TRUE == SetLocalTime(&m_OldDateTime))
|
|
{
|
|
//
|
|
// Successful restored the old date/time
|
|
// Return the old error code back to AppMgr, since the attempt
|
|
// to set new time had failed
|
|
//
|
|
TRACE("SetDateTime has restored the old time");
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// If we got here, the time to restore to old time has failed!!
|
|
// There is not much we can do :-(
|
|
//
|
|
TRACE1(("SetDateTime failed to set restore the old time %X"), HRESULT_FROM_WIN32(GetLastError()));
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::GetSetTimeZoneParameters(IN ITaskContext *pTaskContext,
|
|
OUT LPTSTR *lpStandardTimeZoneName,
|
|
OUT BOOL *pbEnableDayLightSavings)
|
|
{
|
|
|
|
BSTR bstrParamTimeZoneName = SysAllocString(PARAM_TIMEZONE_STANDARDTIME);
|
|
BSTR bstrParamEnableDayLightSavings = SysAllocString(PARAM_DAYLIGHT_ENABLE);
|
|
HRESULT hr;
|
|
VARIANT varValue;
|
|
LPTSTR szEnableDayLight = NULL;
|
|
HANDLE hProcessHeap = NULL;
|
|
|
|
|
|
ASSERT(pTaskContext);
|
|
ASSERT(lpStandardTimeZoneName);
|
|
ASSERT(pbEnableDayLightSavings);
|
|
|
|
|
|
TRACE("Enter GetSetTimeZoneParameters");
|
|
|
|
(*lpStandardTimeZoneName) = NULL;
|
|
|
|
//
|
|
// Retrieve Standard Time Zone name from TaskContext
|
|
//
|
|
VariantClear(&varValue);
|
|
hr = pTaskContext->GetParameter(bstrParamTimeZoneName,
|
|
&varValue);
|
|
TRACE2("GetParameter %ws returned in CDateTime::GetSetTimeZoneParameters "
|
|
"%X", PARAM_TIMEZONE_STANDARDTIME, hr);
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE2("Non-string(%X) parameter received for %ws in GetParameter "
|
|
"in CDateTime:GetSetTimeZoneParameters",
|
|
V_VT(&varValue), PARAM_TIMEZONE_STANDARDTIME);
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
|
|
hProcessHeap = GetProcessHeap();
|
|
if (NULL == hProcessHeap)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto End;
|
|
}
|
|
|
|
|
|
*lpStandardTimeZoneName = (LPTSTR) HeapAlloc(hProcessHeap, 0,
|
|
((lstrlen(V_BSTR(&varValue)) + 1) * sizeof(TCHAR)));
|
|
if (NULL == *lpStandardTimeZoneName)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto End;
|
|
}
|
|
lstrcpy(*lpStandardTimeZoneName, V_BSTR(&varValue));
|
|
|
|
|
|
//
|
|
// Retrieve EnableDayLightSavings flag from TaskContext
|
|
//
|
|
VariantClear(&varValue);
|
|
hr = pTaskContext->GetParameter(bstrParamEnableDayLightSavings,
|
|
&varValue);
|
|
TRACE2(("GetParameter %ws returned in CDateTime::GetSetTimeZoneParameters\
|
|
%X"), PARAM_DAYLIGHT_ENABLE, hr);
|
|
|
|
if (V_VT(&varValue) != VT_BSTR)
|
|
{
|
|
TRACE2(("Non-string(%X) parameter received for %ws in GetParameter \
|
|
in CDateTime:GetSetTimeZoneParameters"), \
|
|
V_VT(&varValue), PARAM_DAYLIGHT_ENABLE);
|
|
hr = E_INVALIDARG;
|
|
goto End;
|
|
}
|
|
//
|
|
// TODO: Convert String value to WORD
|
|
//
|
|
szEnableDayLight = V_BSTR(&varValue);
|
|
*pbEnableDayLightSavings = ((szEnableDayLight[0] == L'y') || (szEnableDayLight[0] == L'Y')) ? TRUE : FALSE;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
End:
|
|
VariantClear(&varValue);
|
|
SysFreeString(bstrParamTimeZoneName);
|
|
SysFreeString(bstrParamEnableDayLightSavings);
|
|
if (S_OK != hr)
|
|
{
|
|
if (NULL != *lpStandardTimeZoneName)
|
|
{
|
|
HeapFree(hProcessHeap, 0, *lpStandardTimeZoneName);
|
|
*lpStandardTimeZoneName = NULL;
|
|
}
|
|
}
|
|
|
|
TRACE1("Leave GetSetTimeZoneParameters, %x", hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::SetTimeZone(IN ITaskContext *pTaskContext)
|
|
{
|
|
BOOL bEnableDayLightSaving;
|
|
LPTSTR lpTimeZoneStandardName = NULL;
|
|
HRESULT hr;
|
|
PTZINFO pTimeZoneInfoList = NULL;
|
|
PTZINFO pTimeZone = NULL;
|
|
int iCount;
|
|
|
|
|
|
ASSERT(pTaskContext);
|
|
|
|
TRACE("Enter SetTimeZone");
|
|
|
|
hr = GetSetTimeZoneParameters(pTaskContext,
|
|
&lpTimeZoneStandardName,
|
|
&bEnableDayLightSaving);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
//
|
|
// Save the current timezone information - in case this operation
|
|
// has to be rolled back
|
|
//
|
|
ZeroMemory(&m_OldTimeZoneInformation, sizeof(TIME_ZONE_INFORMATION));
|
|
GetTimeZoneInformation(&m_OldTimeZoneInformation);
|
|
m_OldEnableDayLightSaving = GetAllowLocalTimeChange();
|
|
|
|
|
|
//
|
|
// Read the list of possible timezones from the registry
|
|
//
|
|
iCount = ReadTimezones(&pTimeZoneInfoList);
|
|
if (0 >= iCount)
|
|
{
|
|
hr = E_FAIL;
|
|
TRACE1(("SetTimeZone failed to enumerate time zones %X"), hr);
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Search for the specified Time Zone
|
|
//
|
|
for (pTimeZone = pTimeZoneInfoList; pTimeZone; pTimeZone = pTimeZone->next)
|
|
{
|
|
if (0 == lstrcmpi(pTimeZone->szStandardName, lpTimeZoneStandardName))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (NULL != pTimeZone)
|
|
{
|
|
SetTheTimezone(bEnableDayLightSaving, pTimeZone);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// if we got here, there were no matches for the input Time Zone
|
|
//
|
|
hr = E_FAIL;
|
|
TRACE1(("SetDateTime:: There were no TimeZone matching the input %X"), hr);
|
|
}
|
|
|
|
|
|
|
|
CleanupAndExit:
|
|
|
|
if (NULL != lpTimeZoneStandardName)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, lpTimeZoneStandardName);
|
|
}
|
|
|
|
FreeTimezoneList(&pTimeZoneInfoList);
|
|
|
|
TRACE1("Leave SetTimeZone, %x", hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::RollbackSetTimeZone(IN ITaskContext *pTaskContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
ASSERT(pTaskContext);
|
|
|
|
//
|
|
// Set the Time Zone and Enable Daylight savings to previous values
|
|
//
|
|
if (FALSE == SetTimeZoneInformation(&m_OldTimeZoneInformation))
|
|
{
|
|
//
|
|
// There is not much we can do !!
|
|
//
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
SetAllowLocalTimeChange(m_OldEnableDayLightSaving);
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::RollbackSetDateTime(IN ITaskContext *pTaskContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
ASSERT(pTaskContext);
|
|
|
|
//
|
|
// Set the Date/Time to previous values
|
|
// We could have lost sometime in between - but this is the best we can do
|
|
//
|
|
|
|
//
|
|
// Note that Windows NT uses the Daylight Saving Time setting of the
|
|
// current time, not the new time we are setting. Therefore, calling
|
|
// SetLocalTime again, now that the Daylight Saving Time setting is set
|
|
// for the new time, will guarantee the correct result.
|
|
//
|
|
if (TRUE == SetLocalTime(&m_OldDateTime))
|
|
{
|
|
if (TRUE == SetLocalTime(&m_OldDateTime))
|
|
{
|
|
//
|
|
// Success
|
|
//
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we got here, the SetLocalTime call(s) must have failed
|
|
// Unfortunately, there is not much we can do !!
|
|
//
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ReadZoneData
|
|
//
|
|
// Reads the data for a time zone from the registry.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CDateTime::ReadZoneData(PTZINFO zone, HKEY key, LPCTSTR keyname)
|
|
{
|
|
DWORD len;
|
|
|
|
len = sizeof(zone->szDisplayName);
|
|
|
|
if (RegQueryValueEx(key,
|
|
c_szTZDisplayName,
|
|
0,
|
|
NULL,
|
|
(LPBYTE)zone->szDisplayName,
|
|
&len ) != ERROR_SUCCESS)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Under NT, the keyname is the "Standard" name. Values stored
|
|
// under the keyname contain the other strings and binary info
|
|
// related to the time zone. Every time zone must have a standard
|
|
// name, therefore, we save registry space by using the Standard
|
|
// name as the subkey name under the "Time Zones" key.
|
|
//
|
|
len = sizeof(zone->szStandardName);
|
|
|
|
if (RegQueryValueEx(key,
|
|
c_szTZStandardName,
|
|
0,
|
|
NULL,
|
|
(LPBYTE)zone->szStandardName,
|
|
&len ) != ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Use keyname if can't get StandardName value.
|
|
//
|
|
lstrcpyn(zone->szStandardName,
|
|
keyname,
|
|
sizeof(zone->szStandardName) );
|
|
}
|
|
|
|
len = sizeof(zone->szDaylightName);
|
|
|
|
if (RegQueryValueEx(key,
|
|
c_szTZDaylightName,
|
|
0,
|
|
NULL,
|
|
(LPBYTE)zone->szDaylightName,
|
|
&len ) != ERROR_SUCCESS)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
len = sizeof(zone->Bias) +
|
|
sizeof(zone->StandardBias) +
|
|
sizeof(zone->DaylightBias) +
|
|
sizeof(zone->StandardDate) +
|
|
sizeof(zone->DaylightDate);
|
|
|
|
if (RegQueryValueEx(key,
|
|
c_szTZI,
|
|
0,
|
|
NULL,
|
|
(LPBYTE)&zone->Bias,
|
|
&len ) != ERROR_SUCCESS)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// AddZoneToList
|
|
//
|
|
// Inserts a new time zone into a list, sorted by bias and then name.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CDateTime::AddZoneToList(PTZINFO *list,
|
|
PTZINFO zone)
|
|
{
|
|
if (*list)
|
|
{
|
|
PTZINFO curr = *list;
|
|
PTZINFO next = NULL;
|
|
|
|
//
|
|
// Go to end of the list
|
|
//
|
|
while (curr && curr->next)
|
|
{
|
|
curr = curr->next;
|
|
next = curr->next;
|
|
}
|
|
|
|
if (curr)
|
|
{
|
|
curr->next = zone;
|
|
}
|
|
|
|
if (zone)
|
|
{
|
|
zone->next = NULL;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
*list = zone;
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FreeTimezoneList
|
|
//
|
|
// Frees all time zones in the passed list, setting the head to NULL.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CDateTime::FreeTimezoneList(PTZINFO *list)
|
|
{
|
|
while (*list)
|
|
{
|
|
PTZINFO next = (*list)->next;
|
|
|
|
LocalFree((HANDLE)*list);
|
|
|
|
*list = next;
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ReadTimezones
|
|
//
|
|
// Reads the time zone information from the registry.
|
|
// Returns num read, -1 on failure.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int CDateTime::ReadTimezones(PTZINFO *list)
|
|
{
|
|
HKEY key = NULL;
|
|
int count = -1;
|
|
|
|
*list = NULL;
|
|
|
|
if (RegOpenKey( HKEY_LOCAL_MACHINE,
|
|
c_szTimeZones,
|
|
&key ) == ERROR_SUCCESS)
|
|
{
|
|
TCHAR name[TZNAME_SIZE];
|
|
PTZINFO zone = NULL;
|
|
int i;
|
|
|
|
count = 0;
|
|
|
|
for (i = 0;
|
|
RegEnumKey(key, i, name, TZNAME_SIZE) == ERROR_SUCCESS;
|
|
i++)
|
|
{
|
|
HKEY subkey = NULL;
|
|
|
|
if (!zone &&
|
|
((zone = (PTZINFO)LocalAlloc(LPTR, sizeof(TZINFO))) == NULL))
|
|
{
|
|
zone = *list;
|
|
*list = NULL;
|
|
count = -1;
|
|
break;
|
|
}
|
|
|
|
zone->next = NULL;
|
|
|
|
if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Each sub key name under the Time Zones key is the
|
|
// "Standard" name for the Time Zone.
|
|
//
|
|
lstrcpyn(zone->szStandardName, name, TZNAME_SIZE);
|
|
|
|
if (ReadZoneData(zone, subkey, name))
|
|
{
|
|
AddZoneToList(list, zone);
|
|
zone = NULL;
|
|
count++;
|
|
}
|
|
|
|
RegCloseKey(subkey);
|
|
}
|
|
}
|
|
|
|
FreeTimezoneList(&zone);
|
|
RegCloseKey(key);
|
|
}
|
|
|
|
return (count);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetAllowLocalTimeChange
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
TCHAR c_szRegPathTZControl[] = REGSTR_PATH_TIMEZONE;
|
|
TCHAR c_szRegValDisableTZUpdate[] = REGSTR_VAL_TZNOAUTOTIME;
|
|
|
|
BOOL CDateTime::GetAllowLocalTimeChange(void)
|
|
{
|
|
//
|
|
// Assume allowed until we see a disallow flag.
|
|
//
|
|
BOOL result = TRUE;
|
|
HKEY key;
|
|
|
|
if (RegOpenKey( HKEY_LOCAL_MACHINE,
|
|
c_szRegPathTZControl,
|
|
&key ) == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Assume no disallow flag until we see one.
|
|
//
|
|
DWORD value = 0;
|
|
DWORD dwlen = sizeof(value);
|
|
DWORD type;
|
|
|
|
if ((RegQueryValueEx( key,
|
|
c_szRegValDisableTZUpdate,
|
|
NULL,
|
|
&type,
|
|
(LPBYTE)&value,
|
|
&dwlen ) == ERROR_SUCCESS) &&
|
|
((type == REG_DWORD) || (type == REG_BINARY)) &&
|
|
(dwlen == sizeof(value)) && value)
|
|
{
|
|
//
|
|
// Okay, we have a nonzero value, it is either:
|
|
//
|
|
// 1) 0xFFFFFFFF
|
|
// this is set in an inf file for first boot to prevent
|
|
// the base from performing any cutovers during setup.
|
|
//
|
|
// 2) some other value
|
|
// this signifies that the user actualy disabled cutovers
|
|
// *return that local time changes are disabled
|
|
//
|
|
if (value != 0xFFFFFFFF)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(key);
|
|
}
|
|
|
|
return (result);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetAllowLocalTimeChange
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CDateTime::SetAllowLocalTimeChange(BOOL fAllow)
|
|
{
|
|
HKEY key = NULL;
|
|
|
|
if (fAllow)
|
|
{
|
|
//
|
|
// Remove the disallow flag from the registry if it exists.
|
|
//
|
|
if (RegOpenKey( HKEY_LOCAL_MACHINE,
|
|
c_szRegPathTZControl,
|
|
&key ) == ERROR_SUCCESS)
|
|
{
|
|
RegDeleteValue(key, c_szRegValDisableTZUpdate);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Add/set the nonzero disallow flag.
|
|
//
|
|
if (RegCreateKey( HKEY_LOCAL_MACHINE,
|
|
c_szRegPathTZControl,
|
|
&key ) == ERROR_SUCCESS)
|
|
{
|
|
DWORD value = 1;
|
|
|
|
RegSetValueEx( key,
|
|
(LPCTSTR)c_szRegValDisableTZUpdate,
|
|
0UL,
|
|
REG_DWORD,
|
|
(LPBYTE)&value,
|
|
sizeof(value) );
|
|
}
|
|
}
|
|
|
|
if (key)
|
|
{
|
|
RegCloseKey(key);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetTheTimezone
|
|
//
|
|
// Apply the time zone selection.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CDateTime::SetTheTimezone(BOOL bAutoMagicTimeChange, PTZINFO ptzi)
|
|
{
|
|
|
|
TIME_ZONE_INFORMATION tzi;
|
|
|
|
if (!ptzi)
|
|
{
|
|
return;
|
|
}
|
|
|
|
tzi.Bias = ptzi->Bias;
|
|
|
|
if ((bAutoMagicTimeChange == 0) ||
|
|
(ptzi->StandardDate.wMonth == 0))
|
|
{
|
|
//
|
|
// Standard Only.
|
|
//
|
|
tzi.StandardBias = ptzi->StandardBias;
|
|
tzi.DaylightBias = ptzi->StandardBias;
|
|
tzi.StandardDate = ptzi->StandardDate;
|
|
tzi.DaylightDate = ptzi->StandardDate;
|
|
|
|
lstrcpy(tzi.StandardName, ptzi->szStandardName);
|
|
lstrcpy(tzi.DaylightName, ptzi->szStandardName);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Automatically adjust for Daylight Saving Time.
|
|
//
|
|
tzi.StandardBias = ptzi->StandardBias;
|
|
tzi.DaylightBias = ptzi->DaylightBias;
|
|
tzi.StandardDate = ptzi->StandardDate;
|
|
tzi.DaylightDate = ptzi->DaylightDate;
|
|
|
|
lstrcpy(tzi.StandardName, ptzi->szStandardName);
|
|
lstrcpy(tzi.DaylightName, ptzi->szDaylightName);
|
|
}
|
|
|
|
SetAllowLocalTimeChange(bAutoMagicTimeChange);
|
|
|
|
SetTimeZoneInformation(&tzi);
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CDateTime::RaiseSetDateTimeAlert(void)
|
|
{
|
|
CComPtr<IApplianceServices> pAppSrvcs = NULL;
|
|
DWORD dwAlertType = SA_ALERT_TYPE_ATTENTION;
|
|
DWORD dwAlertId = SA_DATETIME_NOT_CONFIGURED_ALERT;
|
|
HRESULT hr = E_FAIL;
|
|
_bstr_t bstrAlertLog(ALERT_LOG_NAME);
|
|
_bstr_t bstrAlertSource(ALERT_SOURCE);
|
|
_variant_t varReplacementStrings;
|
|
_variant_t varRawData;
|
|
LONG lCookie;
|
|
|
|
|
|
SATraceFunction("RaiseSetDateTimeAlert");
|
|
|
|
hr = CoCreateInstance(CLSID_ApplianceServices,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER ,
|
|
IID_IApplianceServices,
|
|
(void**)&pAppSrvcs);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERTMSG(FALSE, L"RaiseSetDateTimeAlert failed at CoCreateInstance");
|
|
TRACE1("RaiseSetDateTimeAlert failed at CoCreateInstance, %x", hr);
|
|
goto End;
|
|
}
|
|
|
|
ASSERT(pAppSrvcs);
|
|
hr = pAppSrvcs->Initialize();
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERTMSG(FALSE, L"RaiseSetDateTimeAlert failed at pAppSrvcs->Initialize");
|
|
TRACE1("RaiseSetDateTimeAlert failed at pAppSrvcs->Initialize, %x", hr);
|
|
goto End;
|
|
}
|
|
|
|
|
|
hr = pAppSrvcs->RaiseAlert(dwAlertType,
|
|
dwAlertId,
|
|
bstrAlertLog,
|
|
bstrAlertSource,
|
|
SA_ALERT_DURATION_ETERNAL,
|
|
&varReplacementStrings,
|
|
&varRawData,
|
|
&lCookie);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERTMSG(FALSE, TEXT("RaiseSetDateTimeAlert failed at pAppSrvcs->RaiseAlert"));
|
|
TRACE1("RaiseSetDateTimeAlert failed at pAppSrvcs->RaiseAlert, %x", hr);
|
|
}
|
|
|
|
|
|
End:
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CDateTime::DoNotRaiseDateTimeAlert(void)
|
|
{
|
|
LONG lReturnValue;
|
|
HKEY hKey = NULL;
|
|
DWORD dwDisposition, dwRaiseDateTimeAlert = 0;
|
|
BOOL bReturnCode = FALSE;
|
|
|
|
SATraceFunction("DoNotRaiseDateTimeAlert");
|
|
|
|
//
|
|
// Write Settings to registry
|
|
//
|
|
lReturnValue = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
REGKEY_SA_DATETIME,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&dwDisposition);
|
|
if (lReturnValue != ERROR_SUCCESS)
|
|
{
|
|
TRACE1("RegCreateKeyEx failed with %X", lReturnValue);
|
|
goto End;
|
|
}
|
|
|
|
//
|
|
// Set RaiseAlert value to 0
|
|
//
|
|
dwRaiseDateTimeAlert = 0;
|
|
lReturnValue = RegSetValueEx(hKey,
|
|
REGSTR_VAL_DATETIME_RAISEALERT,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &dwRaiseDateTimeAlert,
|
|
sizeof(DWORD));
|
|
if (lReturnValue != ERROR_SUCCESS)
|
|
{
|
|
TRACE2("RegSetValueEx of %ws failed with %X", REGSTR_VAL_DATETIME_RAISEALERT, lReturnValue);
|
|
goto End;
|
|
}
|
|
else
|
|
{
|
|
bReturnCode = TRUE;
|
|
}
|
|
|
|
|
|
End:
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
return bReturnCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CDateTime::ShouldRaiseDateTimeAlert(void)
|
|
{
|
|
LONG lReturnValue;
|
|
HKEY hKey = NULL;
|
|
DWORD dwSize, dwType, dwRaiseDateTimeAlert = 0;
|
|
BOOL bReturnCode = TRUE;
|
|
|
|
SATraceFunction("ShouldRaiseDateTimeAlert");
|
|
|
|
//
|
|
// Open HKLM\Software\Microsoft\ServerAppliance\DateTime reg key
|
|
//
|
|
lReturnValue = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REGKEY_SA_DATETIME,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (lReturnValue != ERROR_SUCCESS)
|
|
{
|
|
TRACE1("RegOpenKeyEx failed with %X", lReturnValue);
|
|
goto End;
|
|
}
|
|
|
|
//
|
|
// Read the RaiseAlert reg key
|
|
//
|
|
dwSize = sizeof(DWORD);
|
|
lReturnValue = RegQueryValueEx(hKey,
|
|
REGSTR_VAL_DATETIME_RAISEALERT,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE) &dwRaiseDateTimeAlert,
|
|
&dwSize);
|
|
if (lReturnValue != ERROR_SUCCESS)
|
|
{
|
|
TRACE2("RegQueryValueEx of %ws failed with %X", REGSTR_VAL_DATETIME_RAISEALERT, lReturnValue);
|
|
goto End;
|
|
}
|
|
|
|
if (0 == dwRaiseDateTimeAlert)
|
|
{
|
|
bReturnCode = FALSE;
|
|
}
|
|
|
|
|
|
End:
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
return bReturnCode;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CDateTime::ClearDateTimeAlert(void)
|
|
{
|
|
CComPtr<IApplianceServices> pAppSrvcs = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
_bstr_t bstrAlertLog(ALERT_LOG_NAME);
|
|
BOOL bReturnCode = FALSE;
|
|
|
|
|
|
SATraceFunction("ClearDateTimeAlert");
|
|
|
|
hr = CoCreateInstance(CLSID_ApplianceServices,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER ,
|
|
IID_IApplianceServices,
|
|
(void**)&pAppSrvcs);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERTMSG(FALSE, L"ClearDateTimeAlert failed at CoCreateInstance");
|
|
TRACE1("ClearDateTimeAlert failed at CoCreateInstance, %x", hr);
|
|
goto End;
|
|
}
|
|
|
|
ASSERT(pAppSrvcs);
|
|
hr = pAppSrvcs->Initialize();
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERTMSG(FALSE, L"ClearDateTimeAlert failed at pAppSrvcs->Initialize");
|
|
TRACE1("ClearDateTimeAlert failed at pAppSrvcs->Initialize, %x", hr);
|
|
goto End;
|
|
}
|
|
|
|
|
|
hr = pAppSrvcs->ClearAlertAll(SA_DATETIME_NOT_CONFIGURED_ALERT,
|
|
bstrAlertLog);
|
|
|
|
//
|
|
// DISP_E_MEMBERNOTFOUND means that there were no matching alerts
|
|
//
|
|
if ((hr != DISP_E_MEMBERNOTFOUND) && (FAILED(hr)))
|
|
{
|
|
ASSERTMSG(FALSE, TEXT("ClearDateTimeAlert failed at pAppSrvcs->RaiseAlert"));
|
|
TRACE1("ClearDateTimeAlert failed at pAppSrvcs->RaiseAlert, %x", hr);
|
|
}
|
|
else
|
|
{
|
|
bReturnCode = TRUE;
|
|
}
|
|
|
|
|
|
End:
|
|
return bReturnCode;
|
|
}
|
|
|
|
|
|
|
|
|