76f0418ad6d8bfcf7eaf239b6c6797f2924cc25e
[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 case 128:
110 TRACE(" Start Shell control received\n");
111 return ERROR_SUCCESS;
112
113 case 129:
114 TRACE(" Logoff control received\n");
115 return ERROR_SUCCESS;
116
117 default:
118 TRACE(" Control %lu received\n", dwControl);
119 return ERROR_CALL_NOT_IMPLEMENTED;
120 }
121 }
122
123
124 static
125 DWORD
126 ServiceInit(PHANDLE phEvent)
127 {
128 HANDLE hThread;
129 DWORD dwError;
130
131 /* Initialize the job list */
132 InitializeListHead(&JobListHead);
133
134 /* Initialize the job list lock */
135 RtlInitializeResource(&JobListLock);
136
137 /* Initialize the start list */
138 InitializeListHead(&StartListHead);
139
140 /* Initialize the start list lock */
141 RtlInitializeResource(&StartListLock);
142
143 /* Load stored jobs from the registry */
144 dwError = LoadJobs();
145 if (dwError != ERROR_SUCCESS)
146 return dwError;
147
148 /* Start the RPC thread */
149 hThread = CreateThread(NULL,
150 0,
151 (LPTHREAD_START_ROUTINE)RpcThreadRoutine,
152 NULL,
153 0,
154 NULL);
155 if (!hThread)
156 {
157 ERR("Could not create the RPC thread\n");
158 return GetLastError();
159 }
160
161 CloseHandle(hThread);
162
163 /* Create the scheduler event */
164 *phEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
165 if (*phEvent == NULL)
166 {
167 ERR("Could not create the scheduler event\n");
168 return GetLastError();
169 }
170
171 return ERROR_SUCCESS;
172 }
173
174
175 VOID WINAPI
176 SchedServiceMain(DWORD argc, LPTSTR *argv)
177 {
178 HANDLE hEvent = NULL;
179 DWORD dwError;
180
181 UNREFERENCED_PARAMETER(argc);
182 UNREFERENCED_PARAMETER(argv);
183
184 TRACE("SchedServiceMain() called\n");
185
186 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
187 ServiceControlHandler,
188 NULL);
189 if (!ServiceStatusHandle)
190 {
191 ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
192 return;
193 }
194
195 UpdateServiceStatus(SERVICE_START_PENDING);
196
197 dwError = ServiceInit(&hEvent);
198 if (dwError != ERROR_SUCCESS)
199 {
200 ERR("Service stopped (dwError: %lu\n", dwError);
201 UpdateServiceStatus(SERVICE_STOPPED);
202 return;
203 }
204
205 UpdateServiceStatus(SERVICE_RUNNING);
206
207 for (;;)
208 {
209 /* Leave the loop, if the service has to be stopped */
210 if (bStopService)
211 break;
212
213 /* Wait for the next timeout */
214 WaitForSingleObject(hEvent, 5000);
215 TRACE("Service running!\n");
216 }
217
218 /* Close the scheduler event handle */
219 CloseHandle(hEvent);
220
221 /* Stop the service */
222 UpdateServiceStatus(SERVICE_STOPPED);
223 }
224
225
226 BOOL WINAPI
227 DllMain(HINSTANCE hinstDLL,
228 DWORD fdwReason,
229 LPVOID lpvReserved)
230 {
231 switch (fdwReason)
232 {
233 case DLL_PROCESS_ATTACH:
234 DisableThreadLibraryCalls(hinstDLL);
235 break;
236
237 case DLL_PROCESS_DETACH:
238 break;
239 }
240
241 return TRUE;
242 }