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.

203 lines
5.9 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: schdsrvc.cxx
  7. //
  8. // Contents:
  9. //
  10. // Notes: Hack around the service not being started when creating tasks
  11. //
  12. // Functions: StartScheduler
  13. //
  14. // History: 2/19/1997 SusiA Cut from MSDN
  15. //
  16. // Notes: This function works for either Win9x or Windows NT.
  17. // If the service is running but paused, does nothing.//
  18. //____________________________________________________________________________
  19. #include "precomp.h"
  20. extern OSVERSIONINFOA g_OSVersionInfo;
  21. #undef TRACE
  22. #define TRACE(x) //OutputDebugString(x)
  23. #define MAX_SERVICE_WAIT_TIME 90000 // a minute and a half
  24. #define SCHED_CLASS TEXT("SAGEWINDOWCLASS")
  25. #define SCHED_TITLE TEXT("SYSTEM AGENT COM WINDOW")
  26. #define SCHED_SERVICE_APP_NAME TEXT("mstask.exe")
  27. #define SCHED_SERVICE_NAME TEXT("Schedule")
  28. DWORD StartScheduler()
  29. {
  30. DWORD dwTimeOut;
  31. DWORD dwError;
  32. if (g_OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  33. {
  34. // Start the Win9X version of TaskScheduler.
  35. HWND hwnd = FindWindow(SCHED_CLASS, SCHED_TITLE);
  36. if (hwnd != NULL)
  37. { // It is already running.
  38. return ERROR_SUCCESS;
  39. }
  40. //
  41. // Execute the task scheduler process.
  42. //
  43. STARTUPINFO sui;
  44. PROCESS_INFORMATION pi;
  45. ZeroMemory(&sui, sizeof(sui));
  46. sui.cb = sizeof (STARTUPINFO);
  47. TCHAR szApp[MAX_PATH];
  48. LPTSTR pszPath;
  49. DWORD dwRet = SearchPath(NULL,
  50. SCHED_SERVICE_APP_NAME,
  51. NULL,
  52. MAX_PATH,
  53. szApp,
  54. &pszPath);
  55. if (dwRet == 0)
  56. {
  57. return GetLastError();
  58. }
  59. BOOL fRet = CreateProcess(szApp, NULL, NULL, NULL, FALSE,
  60. CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
  61. NULL, NULL, &sui, &pi);
  62. if (fRet == 0)
  63. {
  64. return GetLastError();
  65. }
  66. // Now that the process is started, let's wait until the window
  67. // exists before we decide to return success.
  68. dwTimeOut = GetTickCount() + MAX_SERVICE_WAIT_TIME;
  69. dwError = ERROR_SERVICE_NEVER_STARTED;
  70. while (GetTickCount() < dwTimeOut)
  71. {
  72. if (FindWindow(SCHED_CLASS, SCHED_TITLE))
  73. {
  74. dwError = ERROR_SUCCESS;
  75. break;
  76. }
  77. Sleep(1000);
  78. }
  79. CloseHandle(pi.hProcess);
  80. CloseHandle(pi.hThread);
  81. return dwError;
  82. }
  83. else
  84. {
  85. // If not Win95 then start the NT version as a TaskScheduler service.
  86. SC_HANDLE hSC = NULL;
  87. SC_HANDLE hSchSvc = NULL;
  88. hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  89. if (hSC == NULL)
  90. {
  91. return GetLastError();
  92. }
  93. hSchSvc = OpenService(hSC,
  94. SCHED_SERVICE_NAME,
  95. SERVICE_START | SERVICE_QUERY_STATUS);
  96. CloseServiceHandle(hSC);
  97. if (hSchSvc == NULL)
  98. {
  99. return GetLastError();
  100. }
  101. SERVICE_STATUS SvcStatus;
  102. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  103. {
  104. CloseServiceHandle(hSchSvc);
  105. return GetLastError();
  106. }
  107. if (SvcStatus.dwCurrentState == SERVICE_RUNNING)
  108. {
  109. // The service is already running.
  110. CloseServiceHandle(hSchSvc);
  111. return ERROR_SUCCESS;
  112. }
  113. if (StartService(hSchSvc, 0, NULL) == FALSE)
  114. {
  115. CloseServiceHandle(hSchSvc);
  116. return GetLastError();
  117. }
  118. dwTimeOut = GetTickCount() + MAX_SERVICE_WAIT_TIME;
  119. BOOL bContinue = TRUE;
  120. dwError = ERROR_SERVICE_NEVER_STARTED;
  121. while (bContinue)
  122. {
  123. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  124. {
  125. dwError = GetLastError();
  126. break;
  127. }
  128. switch (SvcStatus.dwCurrentState)
  129. {
  130. // This is good!
  131. case SERVICE_RUNNING:
  132. dwError = ERROR_SUCCESS;
  133. // Fall through
  134. // These are bad
  135. case SERVICE_STOPPED:
  136. case SERVICE_STOP_PENDING:
  137. case SERVICE_PAUSE_PENDING:
  138. case SERVICE_PAUSED:
  139. bContinue = FALSE;
  140. break;
  141. default:
  142. if (GetTickCount() < dwTimeOut)
  143. {
  144. // How long to sleep? According to the SDK use a tenth of the wait hint
  145. // and floor/ceil it between 1 and 10 seconds.
  146. DWORD dwSleep = SvcStatus.dwWaitHint / 10;
  147. if (dwSleep < 1000)
  148. {
  149. dwSleep = 1000;
  150. }
  151. else if (dwSleep > 10000)
  152. {
  153. dwSleep = 10000;
  154. }
  155. TRACE("########## Waiting for Task Scheduler service to be started...\n");
  156. Sleep(dwSleep);
  157. }
  158. else
  159. {
  160. TRACE("########## Starting Task Scheduler service timed out...\n");
  161. bContinue = FALSE;
  162. }
  163. break;
  164. }
  165. }
  166. CloseServiceHandle(hSchSvc);
  167. TRACE("########## Stop waiting for Task Scheduler service to start...\n");
  168. return dwError;
  169. }
  170. }