windows-nt/Source/XPSP1/NT/com/mobile/syncmgr/dll/schdsrvc.cxx
2020-09-26 16:20:57 +08:00

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;
}
}