Source code of Windows XP (NT5)
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.

411 lines
11 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Scheduling Agent Service
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  7. //
  8. // File: enable.cxx
  9. //
  10. // Contents: Code to enable/disable the service.
  11. //
  12. // Classes: None.
  13. //
  14. // Functions: StringFromTrigger, CreateFolders, GetDaysOfWeekString,
  15. // GetExitCodeString, GetSageExitCodeString
  16. //
  17. // History: 10-Jun-96 EricB Created.
  18. //
  19. //-----------------------------------------------------------------------------
  20. #include "..\pch\headers.hxx"
  21. #pragma hdrstop
  22. #include "..\inc\resource.h"
  23. #include "..\inc\misc.hxx"
  24. #include "..\inc\debug.hxx"
  25. #include "..\..\inc\sadat.hxx"
  26. HRESULT WillAnyJobsRun(void);
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Function: AutoStart
  30. //
  31. // Synopsis: Persists the autostart state in the registry.
  32. //
  33. // Arguments: [fAutoStart] - If true, service is set to autostart.
  34. //
  35. // Returns: HRESULTs
  36. //
  37. // Notes: FormatMessage allocates the return string. Use LocalFree() to
  38. // deallocate.
  39. //
  40. // The "Run" key is written to on both platforms.
  41. // The "RunServices" key is written to on _CHICAGO_ only.
  42. // ChangeServiceConfig is called on NT only.
  43. //
  44. //----------------------------------------------------------------------------
  45. HRESULT
  46. AutoStart(BOOL fAutoStart)
  47. {
  48. schDebugOut((DEB_ITRACE, "AutoStart(%s)\n", fAutoStart ? "TRUE" : "FALSE"));
  49. long lRet = 0;
  50. HKEY hRunKey;
  51. DWORD dwDisposition; // ignored
  52. lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  53. REGSTR_PATH_RUN,
  54. 0, // reserved
  55. NULL, // class
  56. 0, // non volatile
  57. KEY_SET_VALUE,
  58. NULL, // security attrs
  59. &hRunKey,
  60. &dwDisposition);
  61. if (lRet != ERROR_SUCCESS)
  62. {
  63. ERR_OUT("AutoStart: RegCreateKeyEx of Run key", lRet);
  64. return HRESULT_FROM_WIN32(lRet);
  65. }
  66. #if defined(_CHICAGO_)
  67. HKEY hRunSvcKey;
  68. lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  69. REGSTR_PATH_RUNSERVICES,
  70. 0, // reserved
  71. NULL, // class
  72. 0, // non volatile
  73. KEY_SET_VALUE,
  74. NULL, // security attrs
  75. &hRunSvcKey,
  76. &dwDisposition);
  77. if (lRet != ERROR_SUCCESS)
  78. {
  79. ERR_OUT("AutoStart: RegCreateKeyEx of RunServices key", lRet);
  80. RegCloseKey(hRunKey);
  81. return HRESULT_FROM_WIN32(lRet);
  82. }
  83. #endif // _CHICAGO_
  84. if (fAutoStart)
  85. {
  86. //
  87. // Set the startup values.
  88. //
  89. #if defined(_CHICAGO_)
  90. lRet = RegSetValueEx(hRunSvcKey,
  91. SCH_RUN_VALUE,
  92. 0,
  93. REG_SZ,
  94. (CONST BYTE *) SCHED_SERVICE_APP_NAME,
  95. sizeof(SCHED_SERVICE_APP_NAME));
  96. if (lRet != ERROR_SUCCESS)
  97. {
  98. ERR_OUT("AutoStart: RegSetValueEx of RunServices key value", lRet);
  99. goto Cleanup0;
  100. }
  101. #endif // _CHICAGO_
  102. #define LogonValue SCHED_SETUP_APP_NAME TEXT(" ") SCHED_FIRSTLOGON_SWITCH
  103. lRet = RegSetValueEx(hRunKey,
  104. SCH_RUN_VALUE,
  105. 0,
  106. REG_SZ,
  107. (CONST BYTE *) LogonValue,
  108. sizeof(LogonValue));
  109. if (lRet != ERROR_SUCCESS)
  110. {
  111. ERR_OUT("AutoStart: RegSetValueEx of Run key value", lRet);
  112. goto Cleanup0;
  113. }
  114. }
  115. else
  116. {
  117. //
  118. // Clear the startup values to disable autostart.
  119. //
  120. #if defined(_CHICAGO_)
  121. lRet = RegDeleteValue(hRunSvcKey, SCH_RUN_VALUE);
  122. if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
  123. {
  124. ERR_OUT("AutoStart: RegDeleteValue of RunService key value", lRet);
  125. goto Cleanup0;
  126. }
  127. #endif // _CHICAGO_
  128. lRet = RegDeleteValue(hRunKey, SCH_RUN_VALUE);
  129. if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
  130. {
  131. ERR_OUT("AutoStart: RegDeleteValue of Run key value", lRet);
  132. goto Cleanup0;
  133. }
  134. }
  135. Cleanup0:
  136. #if defined(_CHICAGO_)
  137. RegCloseKey(hRunSvcKey);
  138. #endif // _CHICAGO_
  139. RegCloseKey(hRunKey);
  140. if (lRet != ERROR_SUCCESS)
  141. {
  142. return HRESULT_FROM_WIN32(lRet);
  143. }
  144. #if !defined(_CHICAGO_)
  145. SC_HANDLE hSC, hSvc;
  146. hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | GENERIC_WRITE);
  147. if (hSC == NULL)
  148. {
  149. lRet = GetLastError();
  150. ERR_OUT("AutoStart: OpenSCManager", lRet);
  151. return HRESULT_FROM_WIN32(lRet);
  152. }
  153. hSvc = OpenService(hSC, g_tszSrvcName, SERVICE_CHANGE_CONFIG);
  154. if (hSvc == NULL)
  155. {
  156. lRet = GetLastError();
  157. ERR_OUT("AutoStart: OpenService", lRet);
  158. CloseServiceHandle(hSC);
  159. return HRESULT_FROM_WIN32(lRet);
  160. }
  161. if (ChangeServiceConfig(hSvc,
  162. SERVICE_NO_CHANGE,
  163. fAutoStart ? SERVICE_AUTO_START :
  164. SERVICE_DEMAND_START,
  165. SERVICE_NO_CHANGE,
  166. NULL,
  167. NULL,
  168. NULL,
  169. NULL,
  170. NULL,
  171. NULL,
  172. NULL) == FALSE)
  173. {
  174. lRet = GetLastError();
  175. ERR_OUT("AutoStart: ChangeServiceConfig", lRet);
  176. }
  177. CloseServiceHandle(hSvc);
  178. CloseServiceHandle(hSC);
  179. #endif // !defined(_CHICAGO_)
  180. return (lRet != 0) ? HRESULT_FROM_WIN32(lRet) : S_OK;
  181. }
  182. //+----------------------------------------------------------------------------
  183. //
  184. // Member: WillAnyJobsRun
  185. //
  186. // Synopsis: Examines the job objects in the scheduler folder to see if any
  187. // will run at some point in the future.
  188. //
  189. // Returns: S_OK if any jobs will run, S_FALSE if no jobs will run, or an
  190. // error code.
  191. //
  192. // Notes: This function is called only during setup; however, it is in
  193. // the task DLL, rather than the setup EXE, in order to avoid
  194. // exporting the CJob methods from the DLL.
  195. //
  196. //-----------------------------------------------------------------------------
  197. HRESULT
  198. WillAnyJobsRun(void)
  199. {
  200. TRACE_FUNCTION(WillAnyJobsRun);
  201. HRESULT hr = S_OK;
  202. DWORD dwRet;
  203. HANDLE hFind;
  204. WIN32_FIND_DATA fd;
  205. //
  206. // Compose the job search string. It will be composed of the following:
  207. // g_TasksFolderInfo.ptszPath\*.TSZ_JOB
  208. //
  209. TCHAR tszPath[MAX_PATH + MAX_PATH];
  210. lstrcpy(tszPath, g_TasksFolderInfo.ptszPath);
  211. lstrcat(tszPath, TEXT("\\*.") TSZ_JOB);
  212. hFind = FindFirstFile(tszPath, &fd);
  213. if (hFind == INVALID_HANDLE_VALUE)
  214. {
  215. dwRet = GetLastError();
  216. if (dwRet == ERROR_FILE_NOT_FOUND)
  217. {
  218. //
  219. // No job files.
  220. //
  221. return S_FALSE;
  222. }
  223. else
  224. {
  225. ERR_OUT("WillAnyJobsRun FindFirstFile", dwRet);
  226. return HRESULT_FROM_WIN32(dwRet);
  227. }
  228. }
  229. SYSTEMTIME stNow;
  230. GetLocalTime(&stNow);
  231. CJob * pJob = CJob::Create();
  232. if (pJob == NULL)
  233. {
  234. ERR_OUT("WillAnyJobsRun CJob::Create", E_OUTOFMEMORY);
  235. return E_OUTOFMEMORY;
  236. }
  237. do
  238. {
  239. schDebugOut((DEB_ITRACE, "Found job " FMT_TSTR "\n", fd.cFileName));
  240. //
  241. // TODO: differentiate between job and queue objects and handle
  242. // accordingly.
  243. //
  244. lstrcpy(tszPath, g_TasksFolderInfo.ptszPath);
  245. lstrcat(tszPath, TEXT("\\"));
  246. lstrcat(tszPath, fd.cFileName);
  247. hr = pJob->LoadP(tszPath, 0, TRUE, FALSE);
  248. if (FAILED(hr))
  249. {
  250. ERR_OUT("WillAnyJobsRun LoadP", hr);
  251. hr = S_OK;
  252. goto CheckNextJob;
  253. }
  254. //
  255. // Check if job can run.
  256. //
  257. DWORD dwFlags;
  258. pJob->GetAllFlags(&dwFlags);
  259. if (!(dwFlags & TASK_FLAG_DISABLED) &&
  260. (dwFlags & JOB_I_FLAG_HAS_APPNAME))
  261. {
  262. //
  263. // LoadTriggers will set or clear the JOB_I_FLAG_HAS_TRIGGERS flag
  264. // as appropriate.
  265. //
  266. hr = pJob->LoadTriggers();
  267. if (FAILED(hr))
  268. {
  269. ERR_OUT("WillAnyJobsRun, pJob->LoadTriggers", hr);
  270. hr = S_OK;
  271. goto CheckNextJob;
  272. }
  273. pJob->GetAllFlags(&dwFlags);
  274. if (dwFlags & JOB_I_FLAG_HAS_TRIGGERS)
  275. {
  276. WORD cRuns = 0;
  277. hr = pJob->GetRunTimesP(&stNow, NULL, &cRuns, 1, NULL, NULL);
  278. if (FAILED(hr))
  279. {
  280. ERR_OUT("WillAnyJobsRun GetRunTimes", hr);
  281. hr = S_OK;
  282. goto CheckNextJob;
  283. }
  284. if (cRuns > 0 || hr == SCHED_S_EVENT_TRIGGER)
  285. {
  286. //
  287. // Finding one is sufficent, lets go home.
  288. //
  289. pJob->Release();
  290. FindClose(hFind);
  291. return S_OK;
  292. }
  293. }
  294. }
  295. CheckNextJob:
  296. if (!FindNextFile(hFind, &fd))
  297. {
  298. dwRet = GetLastError();
  299. if (dwRet == ERROR_NO_MORE_FILES)
  300. {
  301. break;
  302. }
  303. else
  304. {
  305. ERR_OUT("CSchedWorker::WillAnyJobsRun, FindNextFile", dwRet);
  306. hr = HRESULT_FROM_WIN32(dwRet);
  307. goto Cleanup;
  308. }
  309. }
  310. }
  311. while (SUCCEEDED(hr));
  312. Cleanup:
  313. pJob->Release();
  314. FindClose(hFind);
  315. return (FAILED(hr)) ? hr : S_FALSE;
  316. }
  317. //+----------------------------------------------------------------------------
  318. //
  319. // Member: ConditionallyEnableService
  320. //
  321. // Synopsis: If any of the job objects in the scheduler folder will run at
  322. // some point in the future, then the service is enabled.
  323. // Otherwise, it is disabled.
  324. //
  325. // History: 1-15-1997 DavidMun Call SADatCreate if service not
  326. // enabled.
  327. //
  328. //-----------------------------------------------------------------------------
  329. STDAPI_(BOOL)
  330. ConditionallyEnableService(void)
  331. {
  332. BOOL fEnable;
  333. DWORD dwVersion; // For SADatGetData
  334. BYTE bPlatform, brgSvcFlags;
  335. HRESULT hr;
  336. #ifdef _CHICAGO_
  337. fEnable = (WillAnyJobsRun() == S_OK);
  338. #else
  339. fEnable = TRUE;
  340. #endif
  341. AutoStart(fEnable);
  342. hr = SADatGetData(g_TasksFolderInfo.ptszPath,
  343. &dwVersion,
  344. &bPlatform,
  345. &brgSvcFlags);
  346. if (FAILED(hr))
  347. {
  348. brgSvcFlags = 0;
  349. }
  350. //
  351. // The SA.DAT file must be present for the UI to work properly. It
  352. // is created on service start, but if the service isn't enabled,
  353. // the user may open the UI and see the wrong thing. So create the
  354. // file here.
  355. //
  356. hr = SADatCreate(g_TasksFolderInfo.ptszPath,
  357. (BOOL)brgSvcFlags & SA_DAT_SVCFLAG_SVC_RUNNING);
  358. if (FAILED(hr))
  359. {
  360. ERR_OUT("ConditionallyEnableService, SADatCreate", hr);
  361. }
  362. return(fEnable);
  363. }