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.

631 lines
15 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: SchState.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 3/27/1996 RaviR Created
  15. //
  16. //____________________________________________________________________________
  17. #include "..\pch\headers.hxx"
  18. #pragma hdrstop
  19. #include "dbg.h"
  20. #include "macros.h"
  21. #include "..\inc\common.hxx"
  22. #include "..\inc\resource.h"
  23. #include "..\inc\misc.hxx"
  24. #include "resource.h"
  25. #include "..\schedui\schedui.hxx"
  26. #include <StrSafe.h>
  27. #define MAX_MSGLEN 300
  28. #define MAX_SCHED_START_WAIT 60 // seconds
  29. //____________________________________________________________________________
  30. //
  31. // Function: GetSchSvcState
  32. //
  33. // Synopsis: returns the schedul service status
  34. //
  35. // Arguments: [dwState] -- IN
  36. //
  37. // Returns: HRESULT
  38. //
  39. // History: 3/29/1996 RaviR Created
  40. //
  41. //____________________________________________________________________________
  42. HRESULT
  43. GetSchSvcState(
  44. DWORD &dwState)
  45. {
  46. SC_HANDLE hSchSvc = NULL;
  47. HRESULT hr = S_OK;
  48. do
  49. {
  50. hSchSvc = OpenScheduleService(SERVICE_QUERY_STATUS);
  51. if (hSchSvc == NULL)
  52. {
  53. hr = HRESULT_FROM_WIN32(GetLastError());
  54. DEBUG_OUT_LASTERROR;
  55. break;
  56. }
  57. SERVICE_STATUS SvcStatus;
  58. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  59. {
  60. hr = HRESULT_FROM_WIN32(GetLastError());
  61. DEBUG_OUT_LASTERROR;
  62. break;
  63. }
  64. dwState = SvcStatus.dwCurrentState;
  65. } while (0);
  66. if (hSchSvc != NULL)
  67. {
  68. CloseServiceHandle(hSchSvc);
  69. }
  70. return hr;
  71. }
  72. //____________________________________________________________________________
  73. //
  74. // Function: StartScheduler
  75. //
  76. // Synopsis: Start the schedule service
  77. //
  78. // Returns: HRESULT
  79. //
  80. // History: 3/29/1996 RaviR Created
  81. //
  82. //____________________________________________________________________________
  83. HRESULT
  84. StartScheduler(void)
  85. {
  86. SC_HANDLE hSchSvc = NULL;
  87. HRESULT hr = S_OK;
  88. do
  89. {
  90. hSchSvc = OpenScheduleService(
  91. SERVICE_CHANGE_CONFIG | SERVICE_START |
  92. SERVICE_QUERY_STATUS);
  93. if (hSchSvc == NULL)
  94. {
  95. hr = HRESULT_FROM_WIN32(GetLastError());
  96. DEBUG_OUT_LASTERROR;
  97. break;
  98. }
  99. SERVICE_STATUS SvcStatus;
  100. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  101. {
  102. hr = HRESULT_FROM_WIN32(GetLastError());
  103. DEBUG_OUT_LASTERROR;
  104. break;
  105. }
  106. if (SvcStatus.dwCurrentState == SERVICE_RUNNING)
  107. {
  108. // The service is already running.
  109. break;
  110. }
  111. if (StartService(hSchSvc, 0, NULL) == FALSE)
  112. {
  113. hr = HRESULT_FROM_WIN32(GetLastError());
  114. DEBUG_OUT_LASTERROR;
  115. break;
  116. }
  117. } while (0);
  118. if (hSchSvc != NULL)
  119. {
  120. CloseServiceHandle(hSchSvc);
  121. }
  122. return hr;
  123. }
  124. //____________________________________________________________________________
  125. //
  126. // Function: StopScheduler
  127. //
  128. // Synopsis: Stops the schedule service
  129. //
  130. // Returns: HRESULT
  131. //
  132. // History: 3/29/1996 RaviR Created
  133. //
  134. //____________________________________________________________________________
  135. HRESULT
  136. StopScheduler(void)
  137. {
  138. SC_HANDLE hSchSvc = NULL;
  139. HRESULT hr = S_OK;
  140. do
  141. {
  142. hSchSvc = OpenScheduleService(
  143. SERVICE_CHANGE_CONFIG | SERVICE_STOP |
  144. SERVICE_QUERY_STATUS);
  145. if (hSchSvc == NULL)
  146. {
  147. hr = HRESULT_FROM_WIN32(GetLastError());
  148. DEBUG_OUT_LASTERROR;
  149. break;
  150. }
  151. SERVICE_STATUS SvcStatus;
  152. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  153. {
  154. hr = HRESULT_FROM_WIN32(GetLastError());
  155. DEBUG_OUT_LASTERROR;
  156. break;
  157. }
  158. if (SvcStatus.dwCurrentState == SERVICE_STOPPED)
  159. {
  160. // The service is already stopped.
  161. break;
  162. }
  163. if (ControlService(hSchSvc, SERVICE_CONTROL_STOP, &SvcStatus) == FALSE)
  164. {
  165. hr = HRESULT_FROM_WIN32(GetLastError());
  166. DEBUG_OUT_LASTERROR;
  167. break;
  168. }
  169. } while (0);
  170. if (hSchSvc != NULL)
  171. {
  172. CloseServiceHandle(hSchSvc);
  173. }
  174. return hr;
  175. }
  176. //____________________________________________________________________________
  177. //
  178. // Function: PauseScheduler
  179. //
  180. // Synopsis: If fPause==TRUE requests the schedule service to pauses,
  181. // else to continue.
  182. //
  183. // Arguments: [fPause] -- IN
  184. //
  185. // Returns: HRESULT
  186. //
  187. // History: 3/29/1996 RaviR Created
  188. //
  189. //____________________________________________________________________________
  190. HRESULT
  191. PauseScheduler(
  192. BOOL fPause)
  193. {
  194. SC_HANDLE hSchSvc = NULL;
  195. HRESULT hr = S_OK;
  196. do
  197. {
  198. hSchSvc = OpenScheduleService(
  199. SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_STATUS);
  200. if (hSchSvc == NULL)
  201. {
  202. hr = HRESULT_FROM_WIN32(GetLastError());
  203. DEBUG_OUT_LASTERROR;
  204. break;
  205. }
  206. SERVICE_STATUS SvcStatus;
  207. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  208. {
  209. hr = HRESULT_FROM_WIN32(GetLastError());
  210. DEBUG_OUT_LASTERROR;
  211. break;
  212. }
  213. if (fPause == TRUE)
  214. {
  215. if ((SvcStatus.dwCurrentState == SERVICE_PAUSED) ||
  216. (SvcStatus.dwCurrentState == SERVICE_PAUSE_PENDING))
  217. {
  218. // Nothing to do here.
  219. break;
  220. }
  221. else if ((SvcStatus.dwCurrentState == SERVICE_STOPPED) ||
  222. (SvcStatus.dwCurrentState == SERVICE_STOP_PENDING))
  223. {
  224. Win4Assert(0 && "Unexpected");
  225. hr = E_UNEXPECTED;
  226. CHECK_HRESULT(hr);
  227. break;
  228. }
  229. else
  230. {
  231. if (ControlService(hSchSvc, SERVICE_CONTROL_PAUSE, &SvcStatus)
  232. == FALSE)
  233. {
  234. hr = HRESULT_FROM_WIN32(GetLastError());
  235. DEBUG_OUT_LASTERROR;
  236. break;
  237. }
  238. }
  239. }
  240. else // continue
  241. {
  242. if ((SvcStatus.dwCurrentState == SERVICE_RUNNING) ||
  243. (SvcStatus.dwCurrentState == SERVICE_CONTINUE_PENDING))
  244. {
  245. // Nothing to do here.
  246. break;
  247. }
  248. else if ((SvcStatus.dwCurrentState == SERVICE_STOPPED) ||
  249. (SvcStatus.dwCurrentState == SERVICE_STOP_PENDING))
  250. {
  251. Win4Assert(0 && "Unexpected");
  252. hr = E_UNEXPECTED;
  253. CHECK_HRESULT(hr);
  254. break;
  255. }
  256. else
  257. {
  258. if (ControlService(hSchSvc, SERVICE_CONTROL_CONTINUE,
  259. &SvcStatus)
  260. == FALSE)
  261. {
  262. hr = HRESULT_FROM_WIN32(GetLastError());
  263. DEBUG_OUT_LASTERROR;
  264. break;
  265. }
  266. }
  267. }
  268. } while (0);
  269. if (hSchSvc != NULL)
  270. {
  271. CloseServiceHandle(hSchSvc);
  272. }
  273. return hr;
  274. }
  275. //+--------------------------------------------------------------------------
  276. //
  277. // Function: UserCanChangeService
  278. //
  279. // Synopsis: Returns TRUE if the UI should allow the user to invoke
  280. // service start, stop, pause/continue, or at account options.
  281. //
  282. // Returns: TRUE if focus is local machine and OS is win95 or it is NT
  283. // and the user is an admin.
  284. //
  285. // History: 4-16-1997 DavidMun Created
  286. //
  287. //---------------------------------------------------------------------------
  288. BOOL
  289. UserCanChangeService(
  290. LPCTSTR pszServerFocus)
  291. {
  292. if (pszServerFocus)
  293. {
  294. return FALSE;
  295. }
  296. //
  297. // Determine if user is an admin. If not, some items under the
  298. // advanced menu will be disabled.
  299. // BUGBUG A more accurate way to do this would be to attempt to open
  300. // the relevant registry keys and service handle.
  301. //
  302. return IsThreadCallerAnAdmin(NULL);
  303. }
  304. //+--------------------------------------------------------------------------
  305. //
  306. // Function: PromptForServiceStart
  307. //
  308. // Synopsis: If the service is not started or is paused, prompt the user
  309. // to allow us to start/continue it.
  310. //
  311. // Returns: S_OK - service was already running, or was successfully
  312. // started or continued.
  313. // S_FALSE - user elected not to start/continue service
  314. // E_* - error starting/continuing service
  315. //
  316. // History: 4-16-1997 DavidMun Created
  317. //
  318. //---------------------------------------------------------------------------
  319. HRESULT
  320. PromptForServiceStart(
  321. HWND hwnd)
  322. {
  323. HRESULT hr = S_OK;
  324. do
  325. {
  326. //
  327. // Get the current service state
  328. //
  329. DWORD dwState = SERVICE_STOPPED;
  330. hr = GetSchSvcState(dwState);
  331. if (FAILED(hr))
  332. {
  333. dwState = SERVICE_STOPPED;
  334. hr = S_OK; // reset
  335. }
  336. //
  337. // Determine the required action
  338. //
  339. UINT uMsg = 0;
  340. if (dwState == SERVICE_STOPPED ||
  341. dwState == SERVICE_STOP_PENDING)
  342. {
  343. uMsg = IDS_START_SERVICE;
  344. }
  345. else if (dwState == SERVICE_PAUSED ||
  346. dwState == SERVICE_PAUSE_PENDING)
  347. {
  348. uMsg = IDS_CONTINUE_SERVICE;
  349. }
  350. else if (dwState == SERVICE_START_PENDING)
  351. {
  352. uMsg = IDS_START_PENDING;
  353. }
  354. //
  355. // If the service is running, there's nothing to do.
  356. //
  357. if (!uMsg)
  358. {
  359. hr = S_OK;
  360. break;
  361. }
  362. if (uMsg == IDS_START_PENDING)
  363. {
  364. SchedUIMessageDialog(hwnd,
  365. uMsg,
  366. MB_SETFOREGROUND |
  367. MB_TASKMODAL |
  368. MB_ICONINFORMATION |
  369. MB_OK,
  370. NULL);
  371. }
  372. else
  373. {
  374. if (SchedUIMessageDialog(hwnd, uMsg,
  375. MB_SETFOREGROUND |
  376. MB_TASKMODAL |
  377. MB_ICONQUESTION |
  378. MB_YESNO,
  379. NULL)
  380. == IDNO)
  381. {
  382. hr = S_FALSE;
  383. break;
  384. }
  385. }
  386. CWaitCursor waitCursor;
  387. if (uMsg == IDS_START_SERVICE)
  388. {
  389. hr = StartScheduler();
  390. if (FAILED(hr))
  391. {
  392. SchedUIErrorDialog(hwnd, IERR_STARTSVC, (LPTSTR)NULL);
  393. break;
  394. }
  395. // Give the schedule service time to start up.
  396. Sleep(2000);
  397. }
  398. else if (uMsg == IDS_CONTINUE_SERVICE)
  399. {
  400. PauseScheduler(FALSE);
  401. }
  402. for (int count=0; count < 60; count++)
  403. {
  404. GetSchSvcState(dwState);
  405. if (dwState == SERVICE_RUNNING)
  406. {
  407. break;
  408. }
  409. Sleep(1000); // Sleep for 1 seconds.
  410. }
  411. if (dwState != SERVICE_RUNNING)
  412. {
  413. //
  414. // unable to start/continue the service.
  415. //
  416. SchedUIErrorDialog(hwnd,
  417. (uMsg == IDS_START_SERVICE) ? IERR_STARTSVC
  418. : IERR_CONTINUESVC,
  419. (LPTSTR)NULL);
  420. hr = E_FAIL;
  421. break;
  422. }
  423. } while (0);
  424. return hr;
  425. }
  426. //+--------------------------------------------------------------------------
  427. //
  428. // Function: QuietStartContinueService
  429. //
  430. // Synopsis: Start or continue the service without requiring user
  431. // interaction.
  432. //
  433. // Returns: S_OK - service running
  434. // E_FAIL - timeout or failure
  435. //
  436. // History: 5-19-1997 DavidMun Created
  437. //
  438. //---------------------------------------------------------------------------
  439. HRESULT
  440. QuietStartContinueService()
  441. {
  442. HRESULT hr = S_OK;
  443. DWORD dwState = SERVICE_STOPPED;
  444. do
  445. {
  446. hr = GetSchSvcState(dwState);
  447. if (FAILED(hr))
  448. {
  449. dwState = SERVICE_STOPPED;
  450. hr = S_OK; // reset
  451. }
  452. //
  453. // If the service is running, there's nothing to do.
  454. //
  455. if (dwState == SERVICE_RUNNING)
  456. {
  457. break;
  458. }
  459. //
  460. // If it's stopped, request a start. If it's paused, request
  461. // continue.
  462. //
  463. CWaitCursor waitCursor;
  464. switch (dwState)
  465. {
  466. case SERVICE_STOPPED:
  467. case SERVICE_STOP_PENDING:
  468. hr = StartScheduler();
  469. break;
  470. case SERVICE_PAUSED:
  471. case SERVICE_PAUSE_PENDING:
  472. hr = PauseScheduler(FALSE);
  473. break;
  474. }
  475. if (FAILED(hr))
  476. {
  477. CHECK_HRESULT(hr);
  478. break;
  479. }
  480. //
  481. // Wait for its state to change to running
  482. //
  483. for (int count=0; count < MAX_SCHED_START_WAIT; count++)
  484. {
  485. GetSchSvcState(dwState);
  486. if (dwState == SERVICE_RUNNING)
  487. {
  488. break;
  489. }
  490. Sleep(1000); // Sleep for 1 seconds.
  491. }
  492. if (dwState != SERVICE_RUNNING)
  493. {
  494. //
  495. // unable to start/continue the service.
  496. //
  497. hr = E_FAIL;
  498. CHECK_HRESULT(hr);
  499. }
  500. } while (0);
  501. return hr;
  502. }
  503. //____________________________________________________________________________
  504. //
  505. // Function: OpenScheduleService
  506. //
  507. // Synopsis: Opens a handle to the "Schedule" service
  508. //
  509. // Arguments: [dwDesiredAccess] -- desired access
  510. //
  511. // Returns: Handle; if NULL, use GetLastError()
  512. //
  513. // History: 15-Nov-1996 AnirudhS Created
  514. //
  515. //____________________________________________________________________________
  516. SC_HANDLE
  517. OpenScheduleService(DWORD dwDesiredAccess)
  518. {
  519. SC_HANDLE hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  520. if (hSC == NULL)
  521. {
  522. DEBUG_OUT_LASTERROR;
  523. return NULL;
  524. }
  525. SC_HANDLE hSchSvc = OpenService(hSC, SCHED_SERVICE_NAME, dwDesiredAccess);
  526. CloseServiceHandle(hSC);
  527. if (hSchSvc == NULL)
  528. {
  529. DEBUG_OUT_LASTERROR;
  530. }
  531. return hSchSvc;
  532. }