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.
728 lines
19 KiB
728 lines
19 KiB
//#--------------------------------------------------------------
|
|
//
|
|
// File: worker.cpp
|
|
//
|
|
// Synopsis: Implementation of CWorker class methods
|
|
//
|
|
//
|
|
// History:
|
|
//
|
|
// Copyright (C) 1999-2000 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
//----------------------------------------------------------------
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include "nt.h"
|
|
#include "ntrtl.h"
|
|
#include "nturtl.h"
|
|
#include "windows.h"
|
|
#include "ntpoapi.h"
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
|
|
#endif
|
|
#include "shutdowntask.h"
|
|
#include "stdafx.h"
|
|
#include "worker.h"
|
|
#include "appmgrobjs.h"
|
|
|
|
//
|
|
// string constants here
|
|
//
|
|
const WCHAR METHOD_NAME_STRING [] = L"MethodName";
|
|
|
|
const WCHAR POWER_OFF_STRING [] = L"PowerOff";
|
|
|
|
const WCHAR SLEEP_DURATION_STRING [] = L"SleepDuration";
|
|
|
|
const WCHAR SHUTDOWN_TASK_STRING [] = L"ApplianceShutdownTask";
|
|
|
|
//++--------------------------------------------------------------
|
|
//
|
|
// Function: OnTaskComplete
|
|
//
|
|
// Synopsis: This is the IApplianceTask interface method
|
|
//
|
|
// Arguments: [in]
|
|
//
|
|
// Returns: HRESULT - success/failure
|
|
//
|
|
// History: MKarki Created 06/06/2000
|
|
//
|
|
// Called By:
|
|
//
|
|
//----------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CWorker::OnTaskComplete(
|
|
/*[in]*/ IUnknown *pTaskContext,
|
|
/*[in]*/ LONG lTaskResult
|
|
)
|
|
{
|
|
CSATraceFunc objTrace ("CWorker::OnTaskComplete");
|
|
|
|
_ASSERT(pTaskContext);
|
|
|
|
HRESULT hr = S_OK;
|
|
try
|
|
{
|
|
do
|
|
{
|
|
if (NULL == pTaskContext)
|
|
{
|
|
SATraceString (
|
|
"ShutdownTask-OnTaskComplete passed invalid parameter"
|
|
);
|
|
hr = E_POINTER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
//
|
|
// Do nothing on Commit
|
|
//
|
|
if (lTaskResult == SA_TASK_RESULT_COMMIT)
|
|
{
|
|
SATraceString (
|
|
"ShutdownTask-OnTaskComplete-No rollback in OnTaskComplete"
|
|
);
|
|
break;
|
|
}
|
|
|
|
CComPtr <ITaskContext> pTaskParameters;
|
|
//
|
|
// get the task parameters from the context
|
|
//
|
|
hr = pTaskContext->QueryInterface(
|
|
IID_ITaskContext,
|
|
(PVOID*)&pTaskParameters
|
|
);
|
|
if (FAILED (hr))
|
|
{
|
|
SATracePrintf (
|
|
"ShutdownTask-OnTaskComplete failed to query "
|
|
" TaskContext:%x",
|
|
hr
|
|
);
|
|
break;
|
|
}
|
|
|
|
|
|
SA_TASK eTask = NO_TASK;
|
|
//
|
|
// Check which Task is being executed and call that method
|
|
//
|
|
hr = GetMethodName(pTaskParameters, &eTask);
|
|
if (FAILED (hr)) {break;}
|
|
|
|
//
|
|
// initiate the appropriate task now
|
|
//
|
|
switch (eTask)
|
|
{
|
|
case SHUTDOWN:
|
|
hr = InitTask (pTaskParameters);
|
|
break;
|
|
|
|
default:
|
|
SATracePrintf (
|
|
"ShutdownTask-OnTaskComplete passed unknown task type:%d",
|
|
eTask
|
|
);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
}
|
|
while (false);
|
|
}
|
|
catch (...)
|
|
{
|
|
SATraceString (
|
|
"ShutdownTask-OnTaskComplete caught unknown exception"
|
|
);
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return (hr);
|
|
|
|
} // end of CWorker::OnTaskComplete method
|
|
|
|
//++--------------------------------------------------------------
|
|
//
|
|
// Function: OnTaskExecute
|
|
//
|
|
// Synopsis: This is the IApplianceTask interface method
|
|
//
|
|
// Arguments: [in]
|
|
//
|
|
// Returns: HRESULT - success/failure
|
|
//
|
|
// History: MKarki Created 06/06/2000
|
|
//
|
|
// Called By:
|
|
//
|
|
//----------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CWorker::OnTaskExecute (
|
|
/*[in]*/ IUnknown *pTaskContext
|
|
)
|
|
{
|
|
CSATraceFunc objTrace ("ShutdownTask::OnTaskExecute");
|
|
|
|
_ASSERT (pTaskContext);
|
|
|
|
HRESULT hr = S_OK;
|
|
try
|
|
{
|
|
do
|
|
{
|
|
if (NULL == pTaskContext)
|
|
{
|
|
SATraceString (
|
|
"ShutdownTask-OnTaskExecute passed invalid parameter"
|
|
);
|
|
hr = E_POINTER;
|
|
break;
|
|
}
|
|
|
|
CComPtr <ITaskContext> pTaskParameters;
|
|
//
|
|
// get the task parameters from the context
|
|
//
|
|
hr = pTaskContext->QueryInterface(
|
|
IID_ITaskContext,
|
|
(PVOID*)&pTaskParameters
|
|
);
|
|
if (FAILED (hr))
|
|
{
|
|
SATracePrintf (
|
|
"ShutdownTask-OnTaskExecute failed to query "
|
|
" TaskContext:%x",
|
|
hr
|
|
);
|
|
break;
|
|
}
|
|
|
|
|
|
SA_TASK eTask = NO_TASK;
|
|
//
|
|
// Check which Task is being executed and call that method
|
|
//
|
|
hr = GetMethodName(pTaskParameters, &eTask);
|
|
if (FAILED (hr)) {break;}
|
|
|
|
//
|
|
// initiate the appropriate task now
|
|
//
|
|
switch (eTask)
|
|
{
|
|
case SHUTDOWN:
|
|
hr = InitTask (pTaskParameters);
|
|
break;
|
|
|
|
default:
|
|
SATracePrintf (
|
|
"ShutdownTask-OnTaskExecute passed unknown task type:%d",
|
|
eTask
|
|
);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
}
|
|
while (false);
|
|
}
|
|
catch (...)
|
|
{
|
|
SATraceString (
|
|
"ShutdownTask-OnTaskExecute caught unknown exception"
|
|
);
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return (hr);
|
|
|
|
} // end of CWorker::OnTaskExecute method
|
|
|
|
//++--------------------------------------------------------------
|
|
//
|
|
// Function: GetMethodName
|
|
//
|
|
// Synopsis: This is the CUpdateTask private method to obtain
|
|
// the method that the user wants to execute
|
|
//
|
|
// Arguments: [in] ITaskContext* - task context
|
|
// [out] PSA_TASK - task to execute
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History:
|
|
//
|
|
// Called By:
|
|
//
|
|
//----------------------------------------------------------------
|
|
HRESULT
|
|
CWorker::GetMethodName (
|
|
/*[in]*/ ITaskContext *pTaskParameter,
|
|
/*[out]*/ PSA_TASK peTask
|
|
)
|
|
{
|
|
CSATraceFunc objTraceFunc ("CWorker:GetMethodName");
|
|
|
|
_ASSERT(pTaskParameter && peTask);
|
|
|
|
HRESULT hr = S_OK;
|
|
try
|
|
{
|
|
do
|
|
{
|
|
CComVariant vtValue;
|
|
CComBSTR bstrParamName (METHOD_NAME_STRING);
|
|
//
|
|
// get the methodname parameter out of the Context
|
|
//
|
|
hr = pTaskParameter->GetParameter(
|
|
bstrParamName,
|
|
&vtValue
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
SATracePrintf (
|
|
"Shutdown Task failed on ITaskParameter::GetParameter "
|
|
"with error:%x",
|
|
hr
|
|
);
|
|
break;
|
|
}
|
|
|
|
if (V_VT(&vtValue) != VT_BSTR)
|
|
{
|
|
SATracePrintf (
|
|
"Shutdown Task did not receive a string parameter "
|
|
" for method name:%d",
|
|
V_VT(&vtValue)
|
|
);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// check the task now
|
|
//
|
|
if (0 == ::_wcsicmp (V_BSTR (&vtValue), SHUTDOWN_TASK_STRING))
|
|
{
|
|
*peTask = SHUTDOWN;
|
|
}
|
|
else
|
|
{
|
|
SATracePrintf (
|
|
"Shutdown Task was requested an unknown task:%ws",
|
|
V_BSTR (&vtValue)
|
|
);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// succeeded
|
|
//
|
|
}
|
|
while (false);
|
|
|
|
}
|
|
catch (...)
|
|
{
|
|
SATraceString (
|
|
"Shutdown Task caught unknown exception in GetMethodName"
|
|
);
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
if (FAILED(hr)) {*peTask = NO_TASK;}
|
|
|
|
return (hr);
|
|
|
|
} // end of CWorker::GetMethodName method
|
|
|
|
//++--------------------------------------------------------------
|
|
//
|
|
// Function: IsRebootRequested
|
|
//
|
|
// Synopsis: This is the CUpdateTask private method to check
|
|
// if a reboot is requested
|
|
//
|
|
// Arguments: [in] ITaskContext* - task context
|
|
//
|
|
// Returns: BOOL - true (reboot)/false (shutdown)
|
|
//
|
|
// History:
|
|
//
|
|
// Called By:
|
|
//
|
|
//----------------------------------------------------------------
|
|
BOOL
|
|
CWorker::IsRebootRequested (
|
|
/*[in]*/ ITaskContext *pTaskParameter
|
|
)
|
|
{
|
|
CSATraceFunc objTraceFunc ("CWorker::IsRebootRequested");
|
|
|
|
_ASSERT (pTaskParameter);
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL bReboot = TRUE;
|
|
|
|
try
|
|
{
|
|
do
|
|
{
|
|
CComVariant vtValue;
|
|
CComBSTR bstrParamName (POWER_OFF_STRING);
|
|
//
|
|
// get the parameter out of the Context
|
|
//
|
|
hr = pTaskParameter->GetParameter(
|
|
bstrParamName,
|
|
&vtValue
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
SATracePrintf (
|
|
"Shutdown Task failed on ITaskParameter::IsRebootRequested "
|
|
"with error:%x",
|
|
hr
|
|
);
|
|
break;
|
|
}
|
|
|
|
if (V_VT(&vtValue) != VT_BSTR)
|
|
{
|
|
SATracePrintf (
|
|
"Shutdown Task did not receive a string parameter "
|
|
" for method name:%d",
|
|
V_VT(&vtValue)
|
|
);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// check the task now
|
|
//
|
|
if (0 == ::_wcsicmp (V_BSTR (&vtValue), L"0"))
|
|
{
|
|
bReboot = TRUE;
|
|
SATraceString ("Shutdown Task requestd a REBOOT");
|
|
}
|
|
else
|
|
{
|
|
bReboot = FALSE;
|
|
SATraceString ("Shutdown Task requested a SHUTDOWN");
|
|
}
|
|
|
|
//
|
|
// succeeded
|
|
//
|
|
}
|
|
while (false);
|
|
|
|
}
|
|
catch (...)
|
|
{
|
|
SATraceString (
|
|
"Shutdown Task caught unknown exception in IsRebootRequested"
|
|
);
|
|
}
|
|
|
|
return (bReboot);
|
|
|
|
} // end of CWorker::IsRbootRequested method
|
|
|
|
//++--------------------------------------------------------------
|
|
//
|
|
// Function: GetSleepDuration
|
|
//
|
|
// Synopsis: This is the CUpdateTask private method to
|
|
// obtain the Sleep duration requested by the caller
|
|
//
|
|
// Arguments: [in] ITaskContext* - task context
|
|
//
|
|
// Returns: DWORD - Sleep Duration in milliseconds
|
|
//
|
|
// History:
|
|
//
|
|
// Called By:
|
|
//
|
|
//----------------------------------------------------------------
|
|
DWORD
|
|
CWorker::GetSleepDuration (
|
|
/*[in]*/ ITaskContext *pTaskParameter
|
|
)
|
|
{
|
|
CSATraceFunc objTraceFunc ("CWorker::GetSleepDuration");
|
|
|
|
_ASSERT (pTaskParameter);
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSleepDuration = 0;
|
|
|
|
try
|
|
{
|
|
do
|
|
{
|
|
CComVariant vtValue;
|
|
CComBSTR bstrParamName (SLEEP_DURATION_STRING);
|
|
//
|
|
// get the parameter out of the Context
|
|
//
|
|
hr = pTaskParameter->GetParameter(
|
|
bstrParamName,
|
|
&vtValue
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
SATracePrintf (
|
|
"Shutdown Task failed on ITaskParameter::GetSleepDuration "
|
|
"with error:%x",
|
|
hr
|
|
);
|
|
break;
|
|
}
|
|
|
|
if (V_VT(&vtValue) == VT_I4)
|
|
{
|
|
dwSleepDuration = V_I4 (&vtValue);
|
|
}
|
|
else if (V_VT (&vtValue) == VT_I2)
|
|
{
|
|
dwSleepDuration = V_I2 (&vtValue);
|
|
}
|
|
else if (V_VT (&vtValue) == VT_UI4)
|
|
{
|
|
dwSleepDuration = V_UI4 (&vtValue);
|
|
}
|
|
else if (V_VT (&vtValue) == VT_UI2)
|
|
{
|
|
dwSleepDuration = V_UI2 (&vtValue);
|
|
}
|
|
else if (V_VT (&vtValue) == VT_R8)
|
|
{
|
|
dwSleepDuration = (DWORD) V_R8 (&vtValue);
|
|
}
|
|
else
|
|
{
|
|
SATracePrintf (
|
|
"Shutdown Task did not receive a integer parameter "
|
|
" for power off:%d",
|
|
V_VT(&vtValue)
|
|
);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
SATracePrintf (
|
|
"Shutdown task found sleep duration requested:%d millisecs",
|
|
dwSleepDuration
|
|
);
|
|
}
|
|
while (false);
|
|
|
|
}
|
|
catch (...)
|
|
{
|
|
SATraceString (
|
|
"Shutdown Task caught unknown exception in GetSleepDuration"
|
|
);
|
|
}
|
|
|
|
return (dwSleepDuration);
|
|
|
|
} // end of CWorker::IsPowerOffRequired method
|
|
|
|
//++--------------------------------------------------------------
|
|
//
|
|
// Function: InitTask
|
|
//
|
|
// Synopsis: This is the CWorker private method which
|
|
// is responsible for carrying out the shutdown
|
|
//
|
|
// Arguments: [in] ITaskContext*
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: MKarki 06/06/2000 Created
|
|
//
|
|
// Called By: OnTaskComplete/OnTaskExecute methods of IApplianceTask
|
|
// interface
|
|
//
|
|
//----------------------------------------------------------------
|
|
HRESULT
|
|
CWorker::InitTask (
|
|
/*[in]*/ ITaskContext *pTaskParameter
|
|
)
|
|
{
|
|
CSATraceFunc objTrace ("CWorker::InitTask");
|
|
|
|
_ASSERT (pTaskParameter);
|
|
|
|
HRESULT hr = S_OK;
|
|
try
|
|
{
|
|
do
|
|
{
|
|
//
|
|
// Sleep for the time requested
|
|
//
|
|
Sleep (GetSleepDuration (pTaskParameter));
|
|
|
|
//
|
|
// set the shutdown privilege now
|
|
//
|
|
SetShutdownPrivilege ();
|
|
|
|
//
|
|
// now do the required operation - shutdown or reboot
|
|
//
|
|
BOOL bSuccess = InitiateSystemShutdown(
|
|
NULL, // this machine
|
|
NULL, // no message
|
|
0, // no wait
|
|
TRUE, // force app close option
|
|
IsRebootRequested (pTaskParameter) // reboot option
|
|
);
|
|
if (!bSuccess)
|
|
{
|
|
SATraceFailure ("CWorker::InitTask::InitiateSystemShutdown", GetLastError());
|
|
break;
|
|
}
|
|
|
|
//
|
|
// suceess
|
|
//
|
|
}
|
|
while (false);
|
|
}
|
|
catch (...)
|
|
{
|
|
SATraceString (
|
|
"Shutdown Task failed while doing shutdown "
|
|
"with unknown exception"
|
|
);
|
|
}
|
|
|
|
return (hr);
|
|
|
|
} // end of CWorker::InitTask method
|
|
|
|
|
|
//++--------------------------------------------------------------
|
|
//
|
|
// Function: SetShutdownPrivilege
|
|
//
|
|
// Synopsis: This is the CWorker private method which
|
|
// is responsible for giving process SE_SHUTDOWN_NAME
|
|
// priviledge
|
|
//
|
|
//
|
|
// Arguments: none
|
|
//
|
|
// Returns: bool - yes/now
|
|
//
|
|
// History: MKarki 06/06/2000 Created
|
|
//
|
|
// Called By: OnTaskComplete/OnTaskExecute methods of IApplianceTask
|
|
// interface
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
bool
|
|
CWorker::SetShutdownPrivilege(void)
|
|
{
|
|
|
|
CSATraceFunc objTrace ("CWorker::SetShutdownPrivilege");
|
|
|
|
bool bReturn = false;
|
|
HANDLE hProcessToken = NULL;
|
|
|
|
do
|
|
{
|
|
|
|
//
|
|
// Open the process token
|
|
//
|
|
BOOL bRetVal = OpenProcessToken(
|
|
GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&hProcessToken
|
|
);
|
|
if (!bRetVal)
|
|
{
|
|
SATraceFailure (
|
|
"CWorker::SetShutdownPrivilege::OpenProcessToken", GetLastError ()
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// build the privileges structure
|
|
//
|
|
TOKEN_PRIVILEGES tokPriv;
|
|
tokPriv.PrivilegeCount = 1;
|
|
tokPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
//
|
|
// get the LUID of the shutdown privilege
|
|
//
|
|
bRetVal = LookupPrivilegeValue(
|
|
NULL,
|
|
SE_SHUTDOWN_NAME ,
|
|
&tokPriv.Privileges[0].Luid
|
|
);
|
|
if (!bRetVal)
|
|
{
|
|
SATraceFailure (
|
|
"CWorker::SetShutdownPriviledge::LookupPrivilegeValue", GetLastError ()
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// adjust the process token privileges
|
|
//
|
|
bRetVal = AdjustTokenPrivileges(
|
|
hProcessToken,
|
|
FALSE,
|
|
&tokPriv,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (!bRetVal)
|
|
{
|
|
SATraceFailure (
|
|
"CWorker::SetShutdownPriviledge::AdjustTokenPrivileges", GetLastError ()
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// success
|
|
//
|
|
bRetVal = true;
|
|
}
|
|
while (false);
|
|
|
|
//
|
|
// resource cleanup
|
|
//
|
|
if (hProcessToken)
|
|
{
|
|
CloseHandle (hProcessToken);
|
|
}
|
|
|
|
return bReturn;
|
|
|
|
} // end of CWorker::SetShutdownPrivilege method
|
|
|