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.

728 lines
19 KiB

  1. //#--------------------------------------------------------------
  2. //
  3. // File: worker.cpp
  4. //
  5. // Synopsis: Implementation of CWorker class methods
  6. //
  7. //
  8. // History:
  9. //
  10. // Copyright (C) 1999-2000 Microsoft Corporation
  11. // All rights reserved.
  12. //
  13. //----------------------------------------------------------------
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. #include "nt.h"
  18. #include "ntrtl.h"
  19. #include "nturtl.h"
  20. #include "windows.h"
  21. #include "ntpoapi.h"
  22. #ifdef __cplusplus
  23. }
  24. #endif
  25. #include "shutdowntask.h"
  26. #include "stdafx.h"
  27. #include "worker.h"
  28. #include "appmgrobjs.h"
  29. //
  30. // string constants here
  31. //
  32. const WCHAR METHOD_NAME_STRING [] = L"MethodName";
  33. const WCHAR POWER_OFF_STRING [] = L"PowerOff";
  34. const WCHAR SLEEP_DURATION_STRING [] = L"SleepDuration";
  35. const WCHAR SHUTDOWN_TASK_STRING [] = L"ApplianceShutdownTask";
  36. //++--------------------------------------------------------------
  37. //
  38. // Function: OnTaskComplete
  39. //
  40. // Synopsis: This is the IApplianceTask interface method
  41. //
  42. // Arguments: [in]
  43. //
  44. // Returns: HRESULT - success/failure
  45. //
  46. // History: MKarki Created 06/06/2000
  47. //
  48. // Called By:
  49. //
  50. //----------------------------------------------------------------
  51. STDMETHODIMP
  52. CWorker::OnTaskComplete(
  53. /*[in]*/ IUnknown *pTaskContext,
  54. /*[in]*/ LONG lTaskResult
  55. )
  56. {
  57. CSATraceFunc objTrace ("CWorker::OnTaskComplete");
  58. _ASSERT(pTaskContext);
  59. HRESULT hr = S_OK;
  60. try
  61. {
  62. do
  63. {
  64. if (NULL == pTaskContext)
  65. {
  66. SATraceString (
  67. "ShutdownTask-OnTaskComplete passed invalid parameter"
  68. );
  69. hr = E_POINTER;
  70. break;
  71. }
  72. //
  73. //
  74. // Do nothing on Commit
  75. //
  76. if (lTaskResult == SA_TASK_RESULT_COMMIT)
  77. {
  78. SATraceString (
  79. "ShutdownTask-OnTaskComplete-No rollback in OnTaskComplete"
  80. );
  81. break;
  82. }
  83. CComPtr <ITaskContext> pTaskParameters;
  84. //
  85. // get the task parameters from the context
  86. //
  87. hr = pTaskContext->QueryInterface(
  88. IID_ITaskContext,
  89. (PVOID*)&pTaskParameters
  90. );
  91. if (FAILED (hr))
  92. {
  93. SATracePrintf (
  94. "ShutdownTask-OnTaskComplete failed to query "
  95. " TaskContext:%x",
  96. hr
  97. );
  98. break;
  99. }
  100. SA_TASK eTask = NO_TASK;
  101. //
  102. // Check which Task is being executed and call that method
  103. //
  104. hr = GetMethodName(pTaskParameters, &eTask);
  105. if (FAILED (hr)) {break;}
  106. //
  107. // initiate the appropriate task now
  108. //
  109. switch (eTask)
  110. {
  111. case SHUTDOWN:
  112. hr = InitTask (pTaskParameters);
  113. break;
  114. default:
  115. SATracePrintf (
  116. "ShutdownTask-OnTaskComplete passed unknown task type:%d",
  117. eTask
  118. );
  119. hr = E_INVALIDARG;
  120. break;
  121. }
  122. }
  123. while (false);
  124. }
  125. catch (...)
  126. {
  127. SATraceString (
  128. "ShutdownTask-OnTaskComplete caught unknown exception"
  129. );
  130. hr = E_FAIL;
  131. }
  132. return (hr);
  133. } // end of CWorker::OnTaskComplete method
  134. //++--------------------------------------------------------------
  135. //
  136. // Function: OnTaskExecute
  137. //
  138. // Synopsis: This is the IApplianceTask interface method
  139. //
  140. // Arguments: [in]
  141. //
  142. // Returns: HRESULT - success/failure
  143. //
  144. // History: MKarki Created 06/06/2000
  145. //
  146. // Called By:
  147. //
  148. //----------------------------------------------------------------
  149. STDMETHODIMP
  150. CWorker::OnTaskExecute (
  151. /*[in]*/ IUnknown *pTaskContext
  152. )
  153. {
  154. CSATraceFunc objTrace ("ShutdownTask::OnTaskExecute");
  155. _ASSERT (pTaskContext);
  156. HRESULT hr = S_OK;
  157. try
  158. {
  159. do
  160. {
  161. if (NULL == pTaskContext)
  162. {
  163. SATraceString (
  164. "ShutdownTask-OnTaskExecute passed invalid parameter"
  165. );
  166. hr = E_POINTER;
  167. break;
  168. }
  169. CComPtr <ITaskContext> pTaskParameters;
  170. //
  171. // get the task parameters from the context
  172. //
  173. hr = pTaskContext->QueryInterface(
  174. IID_ITaskContext,
  175. (PVOID*)&pTaskParameters
  176. );
  177. if (FAILED (hr))
  178. {
  179. SATracePrintf (
  180. "ShutdownTask-OnTaskExecute failed to query "
  181. " TaskContext:%x",
  182. hr
  183. );
  184. break;
  185. }
  186. SA_TASK eTask = NO_TASK;
  187. //
  188. // Check which Task is being executed and call that method
  189. //
  190. hr = GetMethodName(pTaskParameters, &eTask);
  191. if (FAILED (hr)) {break;}
  192. //
  193. // initiate the appropriate task now
  194. //
  195. switch (eTask)
  196. {
  197. case SHUTDOWN:
  198. hr = InitTask (pTaskParameters);
  199. break;
  200. default:
  201. SATracePrintf (
  202. "ShutdownTask-OnTaskExecute passed unknown task type:%d",
  203. eTask
  204. );
  205. hr = E_INVALIDARG;
  206. break;
  207. }
  208. }
  209. while (false);
  210. }
  211. catch (...)
  212. {
  213. SATraceString (
  214. "ShutdownTask-OnTaskExecute caught unknown exception"
  215. );
  216. hr = E_FAIL;
  217. }
  218. return (hr);
  219. } // end of CWorker::OnTaskExecute method
  220. //++--------------------------------------------------------------
  221. //
  222. // Function: GetMethodName
  223. //
  224. // Synopsis: This is the CUpdateTask private method to obtain
  225. // the method that the user wants to execute
  226. //
  227. // Arguments: [in] ITaskContext* - task context
  228. // [out] PSA_TASK - task to execute
  229. //
  230. // Returns: HRESULT
  231. //
  232. // History:
  233. //
  234. // Called By:
  235. //
  236. //----------------------------------------------------------------
  237. HRESULT
  238. CWorker::GetMethodName (
  239. /*[in]*/ ITaskContext *pTaskParameter,
  240. /*[out]*/ PSA_TASK peTask
  241. )
  242. {
  243. CSATraceFunc objTraceFunc ("CWorker:GetMethodName");
  244. _ASSERT(pTaskParameter && peTask);
  245. HRESULT hr = S_OK;
  246. try
  247. {
  248. do
  249. {
  250. CComVariant vtValue;
  251. CComBSTR bstrParamName (METHOD_NAME_STRING);
  252. //
  253. // get the methodname parameter out of the Context
  254. //
  255. hr = pTaskParameter->GetParameter(
  256. bstrParamName,
  257. &vtValue
  258. );
  259. if (FAILED(hr))
  260. {
  261. SATracePrintf (
  262. "Shutdown Task failed on ITaskParameter::GetParameter "
  263. "with error:%x",
  264. hr
  265. );
  266. break;
  267. }
  268. if (V_VT(&vtValue) != VT_BSTR)
  269. {
  270. SATracePrintf (
  271. "Shutdown Task did not receive a string parameter "
  272. " for method name:%d",
  273. V_VT(&vtValue)
  274. );
  275. hr = E_INVALIDARG;
  276. break;
  277. }
  278. //
  279. // check the task now
  280. //
  281. if (0 == ::_wcsicmp (V_BSTR (&vtValue), SHUTDOWN_TASK_STRING))
  282. {
  283. *peTask = SHUTDOWN;
  284. }
  285. else
  286. {
  287. SATracePrintf (
  288. "Shutdown Task was requested an unknown task:%ws",
  289. V_BSTR (&vtValue)
  290. );
  291. hr = E_INVALIDARG;
  292. break;
  293. }
  294. //
  295. // succeeded
  296. //
  297. }
  298. while (false);
  299. }
  300. catch (...)
  301. {
  302. SATraceString (
  303. "Shutdown Task caught unknown exception in GetMethodName"
  304. );
  305. hr = E_FAIL;
  306. }
  307. if (FAILED(hr)) {*peTask = NO_TASK;}
  308. return (hr);
  309. } // end of CWorker::GetMethodName method
  310. //++--------------------------------------------------------------
  311. //
  312. // Function: IsRebootRequested
  313. //
  314. // Synopsis: This is the CUpdateTask private method to check
  315. // if a reboot is requested
  316. //
  317. // Arguments: [in] ITaskContext* - task context
  318. //
  319. // Returns: BOOL - true (reboot)/false (shutdown)
  320. //
  321. // History:
  322. //
  323. // Called By:
  324. //
  325. //----------------------------------------------------------------
  326. BOOL
  327. CWorker::IsRebootRequested (
  328. /*[in]*/ ITaskContext *pTaskParameter
  329. )
  330. {
  331. CSATraceFunc objTraceFunc ("CWorker::IsRebootRequested");
  332. _ASSERT (pTaskParameter);
  333. HRESULT hr = S_OK;
  334. BOOL bReboot = TRUE;
  335. try
  336. {
  337. do
  338. {
  339. CComVariant vtValue;
  340. CComBSTR bstrParamName (POWER_OFF_STRING);
  341. //
  342. // get the parameter out of the Context
  343. //
  344. hr = pTaskParameter->GetParameter(
  345. bstrParamName,
  346. &vtValue
  347. );
  348. if (FAILED(hr))
  349. {
  350. SATracePrintf (
  351. "Shutdown Task failed on ITaskParameter::IsRebootRequested "
  352. "with error:%x",
  353. hr
  354. );
  355. break;
  356. }
  357. if (V_VT(&vtValue) != VT_BSTR)
  358. {
  359. SATracePrintf (
  360. "Shutdown Task did not receive a string parameter "
  361. " for method name:%d",
  362. V_VT(&vtValue)
  363. );
  364. hr = E_INVALIDARG;
  365. break;
  366. }
  367. //
  368. // check the task now
  369. //
  370. if (0 == ::_wcsicmp (V_BSTR (&vtValue), L"0"))
  371. {
  372. bReboot = TRUE;
  373. SATraceString ("Shutdown Task requestd a REBOOT");
  374. }
  375. else
  376. {
  377. bReboot = FALSE;
  378. SATraceString ("Shutdown Task requested a SHUTDOWN");
  379. }
  380. //
  381. // succeeded
  382. //
  383. }
  384. while (false);
  385. }
  386. catch (...)
  387. {
  388. SATraceString (
  389. "Shutdown Task caught unknown exception in IsRebootRequested"
  390. );
  391. }
  392. return (bReboot);
  393. } // end of CWorker::IsRbootRequested method
  394. //++--------------------------------------------------------------
  395. //
  396. // Function: GetSleepDuration
  397. //
  398. // Synopsis: This is the CUpdateTask private method to
  399. // obtain the Sleep duration requested by the caller
  400. //
  401. // Arguments: [in] ITaskContext* - task context
  402. //
  403. // Returns: DWORD - Sleep Duration in milliseconds
  404. //
  405. // History:
  406. //
  407. // Called By:
  408. //
  409. //----------------------------------------------------------------
  410. DWORD
  411. CWorker::GetSleepDuration (
  412. /*[in]*/ ITaskContext *pTaskParameter
  413. )
  414. {
  415. CSATraceFunc objTraceFunc ("CWorker::GetSleepDuration");
  416. _ASSERT (pTaskParameter);
  417. HRESULT hr = S_OK;
  418. DWORD dwSleepDuration = 0;
  419. try
  420. {
  421. do
  422. {
  423. CComVariant vtValue;
  424. CComBSTR bstrParamName (SLEEP_DURATION_STRING);
  425. //
  426. // get the parameter out of the Context
  427. //
  428. hr = pTaskParameter->GetParameter(
  429. bstrParamName,
  430. &vtValue
  431. );
  432. if (FAILED(hr))
  433. {
  434. SATracePrintf (
  435. "Shutdown Task failed on ITaskParameter::GetSleepDuration "
  436. "with error:%x",
  437. hr
  438. );
  439. break;
  440. }
  441. if (V_VT(&vtValue) == VT_I4)
  442. {
  443. dwSleepDuration = V_I4 (&vtValue);
  444. }
  445. else if (V_VT (&vtValue) == VT_I2)
  446. {
  447. dwSleepDuration = V_I2 (&vtValue);
  448. }
  449. else if (V_VT (&vtValue) == VT_UI4)
  450. {
  451. dwSleepDuration = V_UI4 (&vtValue);
  452. }
  453. else if (V_VT (&vtValue) == VT_UI2)
  454. {
  455. dwSleepDuration = V_UI2 (&vtValue);
  456. }
  457. else if (V_VT (&vtValue) == VT_R8)
  458. {
  459. dwSleepDuration = (DWORD) V_R8 (&vtValue);
  460. }
  461. else
  462. {
  463. SATracePrintf (
  464. "Shutdown Task did not receive a integer parameter "
  465. " for power off:%d",
  466. V_VT(&vtValue)
  467. );
  468. hr = E_INVALIDARG;
  469. break;
  470. }
  471. SATracePrintf (
  472. "Shutdown task found sleep duration requested:%d millisecs",
  473. dwSleepDuration
  474. );
  475. }
  476. while (false);
  477. }
  478. catch (...)
  479. {
  480. SATraceString (
  481. "Shutdown Task caught unknown exception in GetSleepDuration"
  482. );
  483. }
  484. return (dwSleepDuration);
  485. } // end of CWorker::IsPowerOffRequired method
  486. //++--------------------------------------------------------------
  487. //
  488. // Function: InitTask
  489. //
  490. // Synopsis: This is the CWorker private method which
  491. // is responsible for carrying out the shutdown
  492. //
  493. // Arguments: [in] ITaskContext*
  494. //
  495. // Returns: HRESULT
  496. //
  497. // History: MKarki 06/06/2000 Created
  498. //
  499. // Called By: OnTaskComplete/OnTaskExecute methods of IApplianceTask
  500. // interface
  501. //
  502. //----------------------------------------------------------------
  503. HRESULT
  504. CWorker::InitTask (
  505. /*[in]*/ ITaskContext *pTaskParameter
  506. )
  507. {
  508. CSATraceFunc objTrace ("CWorker::InitTask");
  509. _ASSERT (pTaskParameter);
  510. HRESULT hr = S_OK;
  511. try
  512. {
  513. do
  514. {
  515. //
  516. // Sleep for the time requested
  517. //
  518. Sleep (GetSleepDuration (pTaskParameter));
  519. //
  520. // set the shutdown privilege now
  521. //
  522. SetShutdownPrivilege ();
  523. //
  524. // now do the required operation - shutdown or reboot
  525. //
  526. BOOL bSuccess = InitiateSystemShutdown(
  527. NULL, // this machine
  528. NULL, // no message
  529. 0, // no wait
  530. TRUE, // force app close option
  531. IsRebootRequested (pTaskParameter) // reboot option
  532. );
  533. if (!bSuccess)
  534. {
  535. SATraceFailure ("CWorker::InitTask::InitiateSystemShutdown", GetLastError());
  536. break;
  537. }
  538. //
  539. // suceess
  540. //
  541. }
  542. while (false);
  543. }
  544. catch (...)
  545. {
  546. SATraceString (
  547. "Shutdown Task failed while doing shutdown "
  548. "with unknown exception"
  549. );
  550. }
  551. return (hr);
  552. } // end of CWorker::InitTask method
  553. //++--------------------------------------------------------------
  554. //
  555. // Function: SetShutdownPrivilege
  556. //
  557. // Synopsis: This is the CWorker private method which
  558. // is responsible for giving process SE_SHUTDOWN_NAME
  559. // priviledge
  560. //
  561. //
  562. // Arguments: none
  563. //
  564. // Returns: bool - yes/now
  565. //
  566. // History: MKarki 06/06/2000 Created
  567. //
  568. // Called By: OnTaskComplete/OnTaskExecute methods of IApplianceTask
  569. // interface
  570. //
  571. //----------------------------------------------------------------
  572. bool
  573. CWorker::SetShutdownPrivilege(void)
  574. {
  575. CSATraceFunc objTrace ("CWorker::SetShutdownPrivilege");
  576. bool bReturn = false;
  577. HANDLE hProcessToken = NULL;
  578. do
  579. {
  580. //
  581. // Open the process token
  582. //
  583. BOOL bRetVal = OpenProcessToken(
  584. GetCurrentProcess(),
  585. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  586. &hProcessToken
  587. );
  588. if (!bRetVal)
  589. {
  590. SATraceFailure (
  591. "CWorker::SetShutdownPrivilege::OpenProcessToken", GetLastError ()
  592. );
  593. break;
  594. }
  595. //
  596. // build the privileges structure
  597. //
  598. TOKEN_PRIVILEGES tokPriv;
  599. tokPriv.PrivilegeCount = 1;
  600. tokPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  601. //
  602. // get the LUID of the shutdown privilege
  603. //
  604. bRetVal = LookupPrivilegeValue(
  605. NULL,
  606. SE_SHUTDOWN_NAME ,
  607. &tokPriv.Privileges[0].Luid
  608. );
  609. if (!bRetVal)
  610. {
  611. SATraceFailure (
  612. "CWorker::SetShutdownPriviledge::LookupPrivilegeValue", GetLastError ()
  613. );
  614. break;
  615. }
  616. //
  617. // adjust the process token privileges
  618. //
  619. bRetVal = AdjustTokenPrivileges(
  620. hProcessToken,
  621. FALSE,
  622. &tokPriv,
  623. 0,
  624. NULL,
  625. NULL
  626. );
  627. if (!bRetVal)
  628. {
  629. SATraceFailure (
  630. "CWorker::SetShutdownPriviledge::AdjustTokenPrivileges", GetLastError ()
  631. );
  632. break;
  633. }
  634. //
  635. // success
  636. //
  637. bRetVal = true;
  638. }
  639. while (false);
  640. //
  641. // resource cleanup
  642. //
  643. if (hProcessToken)
  644. {
  645. CloseHandle (hProcessToken);
  646. }
  647. return bReturn;
  648. } // end of CWorker::SetShutdownPrivilege method