Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / base / services / schedsvc / schedsvc.c
1 /*
2 * ReactOS Services
3 * Copyright (C) 2015 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS Services
22 * FILE: base/services/schedsvc/schedsvc.c
23 * PURPOSE: Scheduling service
24 * PROGRAMMER: Eric Kohl <eric.kohl@reactos.org>
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "precomp.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(schedsvc);
32
33 /* GLOBALS ******************************************************************/
34
35 static WCHAR ServiceName[] = L"Schedule";
36
37 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
38 static SERVICE_STATUS ServiceStatus;
39
40 static BOOL bStopService = FALSE;
41
42 /* FUNCTIONS *****************************************************************/
43
44 static VOID
45 UpdateServiceStatus(DWORD dwState)
46 {
47 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
48 ServiceStatus.dwCurrentState = dwState;
49
50 if (dwState == SERVICE_PAUSED || dwState == SERVICE_RUNNING)
51 ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
52 SERVICE_ACCEPT_SHUTDOWN |
53 SERVICE_ACCEPT_PAUSE_CONTINUE;
54 else
55 ServiceStatus.dwControlsAccepted = 0;
56
57 ServiceStatus.dwWin32ExitCode = 0;
58 ServiceStatus.dwServiceSpecificExitCode = 0;
59 ServiceStatus.dwCheckPoint = 0;
60
61 if (dwState == SERVICE_START_PENDING ||
62 dwState == SERVICE_STOP_PENDING ||
63 dwState == SERVICE_PAUSE_PENDING ||
64 dwState == SERVICE_CONTINUE_PENDING)
65 ServiceStatus.dwWaitHint = 10000;
66 else
67 ServiceStatus.dwWaitHint = 0;
68
69 SetServiceStatus(ServiceStatusHandle,
70 &ServiceStatus);
71 }
72
73
74 static DWORD WINAPI
75 ServiceControlHandler(DWORD dwControl,
76 DWORD dwEventType,
77 LPVOID lpEventData,
78 LPVOID lpContext)
79 {
80 TRACE("ServiceControlHandler() called\n");
81
82 switch (dwControl)
83 {
84 case SERVICE_CONTROL_STOP:
85 case SERVICE_CONTROL_SHUTDOWN:
86 TRACE(" SERVICE_CONTROL_STOP/SERVICE_CONTROL_SHUTDOWN received\n");
87 UpdateServiceStatus(SERVICE_STOP_PENDING);
88 /* Stop listening to incoming RPC messages */
89 RpcMgmtStopServerListening(NULL);
90 bStopService = TRUE;
91 return ERROR_SUCCESS;
92
93 case SERVICE_CONTROL_PAUSE:
94 TRACE(" SERVICE_CONTROL_PAUSE received\n");
95 UpdateServiceStatus(SERVICE_PAUSED);
96 return ERROR_SUCCESS;
97
98 case SERVICE_CONTROL_CONTINUE:
99 TRACE(" SERVICE_CONTROL_CONTINUE received\n");
100 UpdateServiceStatus(SERVICE_RUNNING);
101 return ERROR_SUCCESS;
102
103 case SERVICE_CONTROL_INTERROGATE:
104 TRACE(" SERVICE_CONTROL_INTERROGATE received\n");
105 SetServiceStatus(ServiceStatusHandle,
106 &ServiceStatus);
107 return ERROR_SUCCESS;
108
109 default:
110 TRACE(" Control %lu received\n", dwControl);
111 return ERROR_CALL_NOT_IMPLEMENTED;
112 }
113 }
114
115
116 static
117 DWORD
118 ServiceInit(PHANDLE phEvent)
119 {
120 HANDLE hThread;
121 DWORD dwError;
122
123 /* Initialize the job list */
124 InitializeListHead(&JobListHead);
125
126 /* Initialize the job list lock */
127 RtlInitializeResource(&JobListLock);
128
129 /* Initialize the start list */
130 InitializeListHead(&StartListHead);
131
132 /* Initialize the start list lock */
133 RtlInitializeResource(&StartListLock);
134
135 /* Load stored jobs from the registry */
136 dwError = LoadJobs();
137 if (dwError != ERROR_SUCCESS)
138 return dwError;
139
140 /* Start the RPC thread */
141 hThread = CreateThread(NULL,
142 0,
143 (LPTHREAD_START_ROUTINE)RpcThreadRoutine,
144 NULL,
145 0,
146 NULL);
147 if (!hThread)
148 {
149 ERR("Could not create the RPC thread\n");
150 return GetLastError();
151 }
152
153 CloseHandle(hThread);
154
155 /* Create the scheduler event */
156 *phEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
157 if (*phEvent == NULL)
158 {
159 ERR("Could not create the scheduler event\n");
160 return GetLastError();
161 }
162
163 return ERROR_SUCCESS;
164 }
165
166
167 VOID WINAPI
168 SchedServiceMain(DWORD argc, LPTSTR *argv)
169 {
170 HANDLE hEvent = NULL;
171 DWORD dwError;
172
173 UNREFERENCED_PARAMETER(argc);
174 UNREFERENCED_PARAMETER(argv);
175
176 TRACE("SchedServiceMain() called\n");
177
178 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
179 ServiceControlHandler,
180 NULL);
181 if (!ServiceStatusHandle)
182 {
183 ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
184 return;
185 }
186
187 UpdateServiceStatus(SERVICE_START_PENDING);
188
189 dwError = ServiceInit(&hEvent);
190 if (dwError != ERROR_SUCCESS)
191 {
192 ERR("Service stopped (dwError: %lu\n", dwError);
193 UpdateServiceStatus(SERVICE_STOPPED);
194 return;
195 }
196
197 UpdateServiceStatus(SERVICE_RUNNING);
198
199 for (;;)
200 {
201 /* Leave the loop, if the service has to be stopped */
202 if (bStopService)
203 break;
204
205 /* Wait for the next timeout */
206 WaitForSingleObject(hEvent, 5000);
207 TRACE("Service running!\n");
208 }
209
210 /* Close the scheduler event handle */
211 CloseHandle(hEvent);
212
213 /* Stop the service */
214 UpdateServiceStatus(SERVICE_STOPPED);
215 }
216
217
218 BOOL WINAPI
219 DllMain(HINSTANCE hinstDLL,
220 DWORD fdwReason,
221 LPVOID lpvReserved)
222 {
223 switch (fdwReason)
224 {
225 case DLL_PROCESS_ATTACH:
226 DisableThreadLibraryCalls(hinstDLL);
227 break;
228
229 case DLL_PROCESS_DETACH:
230 break;
231 }
232
233 return TRUE;
234 }