|
|
//#--------------------------------------------------------------
//
// 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
|