204 lines
5.9 KiB
C++
204 lines
5.9 KiB
C++
//____________________________________________________________________________
|
|
//
|
|
// 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;
|
|
}
|
|
}
|