//____________________________________________________________________________ // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1995 - 1996. // // File: schdsrvc.cxx // // Contents: // // Notes: Hack around the service not being started when creating tasks // // Functions: StartScheduler // // History: 2/19/1997 SusiA Cut from MSDN // // Notes: This function works for either Win9x or Windows NT. // If the service is running but paused, does nothing.// //____________________________________________________________________________ #include "precomp.h" extern OSVERSIONINFOA g_OSVersionInfo; #undef TRACE #define TRACE(x) //OutputDebugString(x) #define MAX_SERVICE_WAIT_TIME 90000 // a minute and a half #define SCHED_CLASS TEXT("SAGEWINDOWCLASS") #define SCHED_TITLE TEXT("SYSTEM AGENT COM WINDOW") #define SCHED_SERVICE_APP_NAME TEXT("mstask.exe") #define SCHED_SERVICE_NAME TEXT("Schedule") DWORD StartScheduler() { DWORD dwTimeOut; DWORD dwError; if (g_OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { // Start the Win9X version of TaskScheduler. HWND hwnd = FindWindow(SCHED_CLASS, SCHED_TITLE); if (hwnd != NULL) { // It is already running. return ERROR_SUCCESS; } // // Execute the task scheduler process. // STARTUPINFO sui; PROCESS_INFORMATION pi; ZeroMemory(&sui, sizeof(sui)); sui.cb = sizeof (STARTUPINFO); TCHAR szApp[MAX_PATH]; LPTSTR pszPath; DWORD dwRet = SearchPath(NULL, SCHED_SERVICE_APP_NAME, NULL, MAX_PATH, szApp, &pszPath); if (dwRet == 0) { return GetLastError(); } BOOL fRet = CreateProcess(szApp, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &sui, &pi); if (fRet == 0) { return GetLastError(); } // Now that the process is started, let's wait until the window // exists before we decide to return success. dwTimeOut = GetTickCount() + MAX_SERVICE_WAIT_TIME; dwError = ERROR_SERVICE_NEVER_STARTED; while (GetTickCount() < dwTimeOut) { if (FindWindow(SCHED_CLASS, SCHED_TITLE)) { dwError = ERROR_SUCCESS; break; } Sleep(1000); } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return dwError; } else { // If not Win95 then start the NT version as a TaskScheduler service. SC_HANDLE hSC = NULL; SC_HANDLE hSchSvc = NULL; hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (hSC == NULL) { return GetLastError(); } hSchSvc = OpenService(hSC, SCHED_SERVICE_NAME, SERVICE_START | SERVICE_QUERY_STATUS); CloseServiceHandle(hSC); if (hSchSvc == NULL) { return GetLastError(); } SERVICE_STATUS SvcStatus; if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE) { CloseServiceHandle(hSchSvc); return GetLastError(); } if (SvcStatus.dwCurrentState == SERVICE_RUNNING) { // The service is already running. CloseServiceHandle(hSchSvc); return ERROR_SUCCESS; } if (StartService(hSchSvc, 0, NULL) == FALSE) { CloseServiceHandle(hSchSvc); return GetLastError(); } dwTimeOut = GetTickCount() + MAX_SERVICE_WAIT_TIME; BOOL bContinue = TRUE; dwError = ERROR_SERVICE_NEVER_STARTED; while (bContinue) { if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE) { dwError = GetLastError(); break; } switch (SvcStatus.dwCurrentState) { // This is good! case SERVICE_RUNNING: dwError = ERROR_SUCCESS; // Fall through // These are bad case SERVICE_STOPPED: case SERVICE_STOP_PENDING: case SERVICE_PAUSE_PENDING: case SERVICE_PAUSED: bContinue = FALSE; break; default: if (GetTickCount() < dwTimeOut) { // How long to sleep? According to the SDK use a tenth of the wait hint // and floor/ceil it between 1 and 10 seconds. DWORD dwSleep = SvcStatus.dwWaitHint / 10; if (dwSleep < 1000) { dwSleep = 1000; } else if (dwSleep > 10000) { dwSleep = 10000; } TRACE("########## Waiting for Task Scheduler service to be started...\n"); Sleep(dwSleep); } else { TRACE("########## Starting Task Scheduler service timed out...\n"); bContinue = FALSE; } break; } } CloseServiceHandle(hSchSvc); TRACE("########## Stop waiting for Task Scheduler service to start...\n"); return dwError; } }