//+---------------------------------------------------------------------------- // // Scheduling Agent Service // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996. // // File: enable.cxx // // Contents: Code to enable/disable the service. // // Classes: None. // // Functions: StringFromTrigger, CreateFolders, GetDaysOfWeekString, // GetExitCodeString, GetSageExitCodeString // // History: 10-Jun-96 EricB Created. // //----------------------------------------------------------------------------- #include "..\pch\headers.hxx" #pragma hdrstop #include "..\inc\resource.h" #include "..\inc\misc.hxx" #include "..\inc\debug.hxx" #include "..\..\inc\sadat.hxx" HRESULT WillAnyJobsRun(void); //+--------------------------------------------------------------------------- // // Function: AutoStart // // Synopsis: Persists the autostart state in the registry. // // Arguments: [fAutoStart] - If true, service is set to autostart. // // Returns: HRESULTs // // Notes: FormatMessage allocates the return string. Use LocalFree() to // deallocate. // // The "Run" key is written to on both platforms. // The "RunServices" key is written to on _CHICAGO_ only. // ChangeServiceConfig is called on NT only. // //---------------------------------------------------------------------------- HRESULT AutoStart(BOOL fAutoStart) { schDebugOut((DEB_ITRACE, "AutoStart(%s)\n", fAutoStart ? "TRUE" : "FALSE")); long lRet = 0; HKEY hRunKey; DWORD dwDisposition; // ignored lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, 0, // reserved NULL, // class 0, // non volatile KEY_SET_VALUE, NULL, // security attrs &hRunKey, &dwDisposition); if (lRet != ERROR_SUCCESS) { ERR_OUT("AutoStart: RegCreateKeyEx of Run key", lRet); return HRESULT_FROM_WIN32(lRet); } #if defined(_CHICAGO_) HKEY hRunSvcKey; lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNSERVICES, 0, // reserved NULL, // class 0, // non volatile KEY_SET_VALUE, NULL, // security attrs &hRunSvcKey, &dwDisposition); if (lRet != ERROR_SUCCESS) { ERR_OUT("AutoStart: RegCreateKeyEx of RunServices key", lRet); RegCloseKey(hRunKey); return HRESULT_FROM_WIN32(lRet); } #endif // _CHICAGO_ if (fAutoStart) { // // Set the startup values. // #if defined(_CHICAGO_) lRet = RegSetValueEx(hRunSvcKey, SCH_RUN_VALUE, 0, REG_SZ, (CONST BYTE *) SCHED_SERVICE_APP_NAME, sizeof(SCHED_SERVICE_APP_NAME)); if (lRet != ERROR_SUCCESS) { ERR_OUT("AutoStart: RegSetValueEx of RunServices key value", lRet); goto Cleanup0; } #endif // _CHICAGO_ #define LogonValue SCHED_SETUP_APP_NAME TEXT(" ") SCHED_FIRSTLOGON_SWITCH lRet = RegSetValueEx(hRunKey, SCH_RUN_VALUE, 0, REG_SZ, (CONST BYTE *) LogonValue, sizeof(LogonValue)); if (lRet != ERROR_SUCCESS) { ERR_OUT("AutoStart: RegSetValueEx of Run key value", lRet); goto Cleanup0; } } else { // // Clear the startup values to disable autostart. // #if defined(_CHICAGO_) lRet = RegDeleteValue(hRunSvcKey, SCH_RUN_VALUE); if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND) { ERR_OUT("AutoStart: RegDeleteValue of RunService key value", lRet); goto Cleanup0; } #endif // _CHICAGO_ lRet = RegDeleteValue(hRunKey, SCH_RUN_VALUE); if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND) { ERR_OUT("AutoStart: RegDeleteValue of Run key value", lRet); goto Cleanup0; } } Cleanup0: #if defined(_CHICAGO_) RegCloseKey(hRunSvcKey); #endif // _CHICAGO_ RegCloseKey(hRunKey); if (lRet != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(lRet); } #if !defined(_CHICAGO_) SC_HANDLE hSC, hSvc; hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | GENERIC_WRITE); if (hSC == NULL) { lRet = GetLastError(); ERR_OUT("AutoStart: OpenSCManager", lRet); return HRESULT_FROM_WIN32(lRet); } hSvc = OpenService(hSC, g_tszSrvcName, SERVICE_CHANGE_CONFIG); if (hSvc == NULL) { lRet = GetLastError(); ERR_OUT("AutoStart: OpenService", lRet); CloseServiceHandle(hSC); return HRESULT_FROM_WIN32(lRet); } if (ChangeServiceConfig(hSvc, SERVICE_NO_CHANGE, fAutoStart ? SERVICE_AUTO_START : SERVICE_DEMAND_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == FALSE) { lRet = GetLastError(); ERR_OUT("AutoStart: ChangeServiceConfig", lRet); } CloseServiceHandle(hSvc); CloseServiceHandle(hSC); #endif // !defined(_CHICAGO_) return (lRet != 0) ? HRESULT_FROM_WIN32(lRet) : S_OK; } //+---------------------------------------------------------------------------- // // Member: WillAnyJobsRun // // Synopsis: Examines the job objects in the scheduler folder to see if any // will run at some point in the future. // // Returns: S_OK if any jobs will run, S_FALSE if no jobs will run, or an // error code. // // Notes: This function is called only during setup; however, it is in // the task DLL, rather than the setup EXE, in order to avoid // exporting the CJob methods from the DLL. // //----------------------------------------------------------------------------- HRESULT WillAnyJobsRun(void) { TRACE_FUNCTION(WillAnyJobsRun); HRESULT hr = S_OK; DWORD dwRet; HANDLE hFind; WIN32_FIND_DATA fd; // // Compose the job search string. It will be composed of the following: // g_TasksFolderInfo.ptszPath\*.TSZ_JOB // TCHAR tszPath[MAX_PATH + MAX_PATH]; lstrcpy(tszPath, g_TasksFolderInfo.ptszPath); lstrcat(tszPath, TEXT("\\*.") TSZ_JOB); hFind = FindFirstFile(tszPath, &fd); if (hFind == INVALID_HANDLE_VALUE) { dwRet = GetLastError(); if (dwRet == ERROR_FILE_NOT_FOUND) { // // No job files. // return S_FALSE; } else { ERR_OUT("WillAnyJobsRun FindFirstFile", dwRet); return HRESULT_FROM_WIN32(dwRet); } } SYSTEMTIME stNow; GetLocalTime(&stNow); CJob * pJob = CJob::Create(); if (pJob == NULL) { ERR_OUT("WillAnyJobsRun CJob::Create", E_OUTOFMEMORY); return E_OUTOFMEMORY; } do { schDebugOut((DEB_ITRACE, "Found job " FMT_TSTR "\n", fd.cFileName)); // // TODO: differentiate between job and queue objects and handle // accordingly. // lstrcpy(tszPath, g_TasksFolderInfo.ptszPath); lstrcat(tszPath, TEXT("\\")); lstrcat(tszPath, fd.cFileName); hr = pJob->LoadP(tszPath, 0, TRUE, FALSE); if (FAILED(hr)) { ERR_OUT("WillAnyJobsRun LoadP", hr); hr = S_OK; goto CheckNextJob; } // // Check if job can run. // DWORD dwFlags; pJob->GetAllFlags(&dwFlags); if (!(dwFlags & TASK_FLAG_DISABLED) && (dwFlags & JOB_I_FLAG_HAS_APPNAME)) { // // LoadTriggers will set or clear the JOB_I_FLAG_HAS_TRIGGERS flag // as appropriate. // hr = pJob->LoadTriggers(); if (FAILED(hr)) { ERR_OUT("WillAnyJobsRun, pJob->LoadTriggers", hr); hr = S_OK; goto CheckNextJob; } pJob->GetAllFlags(&dwFlags); if (dwFlags & JOB_I_FLAG_HAS_TRIGGERS) { WORD cRuns = 0; hr = pJob->GetRunTimesP(&stNow, NULL, &cRuns, 1, NULL, NULL); if (FAILED(hr)) { ERR_OUT("WillAnyJobsRun GetRunTimes", hr); hr = S_OK; goto CheckNextJob; } if (cRuns > 0 || hr == SCHED_S_EVENT_TRIGGER) { // // Finding one is sufficent, lets go home. // pJob->Release(); FindClose(hFind); return S_OK; } } } CheckNextJob: if (!FindNextFile(hFind, &fd)) { dwRet = GetLastError(); if (dwRet == ERROR_NO_MORE_FILES) { break; } else { ERR_OUT("CSchedWorker::WillAnyJobsRun, FindNextFile", dwRet); hr = HRESULT_FROM_WIN32(dwRet); goto Cleanup; } } } while (SUCCEEDED(hr)); Cleanup: pJob->Release(); FindClose(hFind); return (FAILED(hr)) ? hr : S_FALSE; } //+---------------------------------------------------------------------------- // // Member: ConditionallyEnableService // // Synopsis: If any of the job objects in the scheduler folder will run at // some point in the future, then the service is enabled. // Otherwise, it is disabled. // // History: 1-15-1997 DavidMun Call SADatCreate if service not // enabled. // //----------------------------------------------------------------------------- STDAPI_(BOOL) ConditionallyEnableService(void) { BOOL fEnable; DWORD dwVersion; // For SADatGetData BYTE bPlatform, brgSvcFlags; HRESULT hr; #ifdef _CHICAGO_ fEnable = (WillAnyJobsRun() == S_OK); #else fEnable = TRUE; #endif AutoStart(fEnable); hr = SADatGetData(g_TasksFolderInfo.ptszPath, &dwVersion, &bPlatform, &brgSvcFlags); if (FAILED(hr)) { brgSvcFlags = 0; } // // The SA.DAT file must be present for the UI to work properly. It // is created on service start, but if the service isn't enabled, // the user may open the UI and see the wrong thing. So create the // file here. // hr = SADatCreate(g_TasksFolderInfo.ptszPath, (BOOL)brgSvcFlags & SA_DAT_SVCFLAG_SVC_RUNNING); if (FAILED(hr)) { ERR_OUT("ConditionallyEnableService, SADatCreate", hr); } return(fEnable); }