[SCHEDSVC]
[reactos.git] / reactos / 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 /* FUNCTIONS *****************************************************************/
41
42 static VOID
43 UpdateServiceStatus(DWORD dwState)
44 {
45 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
46 ServiceStatus.dwCurrentState = dwState;
47 ServiceStatus.dwControlsAccepted = 0;
48 ServiceStatus.dwWin32ExitCode = 0;
49 ServiceStatus.dwServiceSpecificExitCode = 0;
50 ServiceStatus.dwCheckPoint = 0;
51
52 if (dwState == SERVICE_START_PENDING ||
53 dwState == SERVICE_STOP_PENDING ||
54 dwState == SERVICE_PAUSE_PENDING ||
55 dwState == SERVICE_CONTINUE_PENDING)
56 ServiceStatus.dwWaitHint = 10000;
57 else
58 ServiceStatus.dwWaitHint = 0;
59
60 SetServiceStatus(ServiceStatusHandle,
61 &ServiceStatus);
62 }
63
64
65 static DWORD WINAPI
66 ServiceControlHandler(DWORD dwControl,
67 DWORD dwEventType,
68 LPVOID lpEventData,
69 LPVOID lpContext)
70 {
71 TRACE("ServiceControlHandler() called\n");
72
73 switch (dwControl)
74 {
75 case SERVICE_CONTROL_STOP:
76 TRACE(" SERVICE_CONTROL_STOP received\n");
77 UpdateServiceStatus(SERVICE_STOP_PENDING);
78 /* Stop listening to incoming RPC messages */
79 RpcMgmtStopServerListening(NULL);
80 UpdateServiceStatus(SERVICE_STOPPED);
81 return ERROR_SUCCESS;
82
83 case SERVICE_CONTROL_PAUSE:
84 TRACE(" SERVICE_CONTROL_PAUSE received\n");
85 UpdateServiceStatus(SERVICE_PAUSED);
86 return ERROR_SUCCESS;
87
88 case SERVICE_CONTROL_CONTINUE:
89 TRACE(" SERVICE_CONTROL_CONTINUE received\n");
90 UpdateServiceStatus(SERVICE_RUNNING);
91 return ERROR_SUCCESS;
92
93 case SERVICE_CONTROL_INTERROGATE:
94 TRACE(" SERVICE_CONTROL_INTERROGATE received\n");
95 SetServiceStatus(ServiceStatusHandle,
96 &ServiceStatus);
97 return ERROR_SUCCESS;
98
99 case SERVICE_CONTROL_SHUTDOWN:
100 TRACE(" SERVICE_CONTROL_SHUTDOWN received\n");
101 UpdateServiceStatus(SERVICE_STOP_PENDING);
102 RpcMgmtStopServerListening(NULL);
103 UpdateServiceStatus(SERVICE_STOPPED);
104 return ERROR_SUCCESS;
105
106 default :
107 TRACE(" Control %lu received\n", dwControl);
108 return ERROR_CALL_NOT_IMPLEMENTED;
109 }
110 }
111
112
113 static
114 DWORD
115 ServiceInit(VOID)
116 {
117 HANDLE hThread;
118 DWORD dwError;
119
120 /* Initialize the job list */
121 InitializeListHead(&JobListHead);
122
123 /* Initialize the job list lock */
124 RtlInitializeResource(&JobListLock);
125
126 /* Initialize the start list */
127 InitializeListHead(&StartListHead);
128
129 /* Initialize the start list lock */
130 RtlInitializeResource(&StartListLock);
131
132 /* Load stored jobs from the registry */
133 dwError = LoadJobs();
134 if (dwError != ERROR_SUCCESS)
135 return dwError;
136
137 /* Start the RPC thread */
138 hThread = CreateThread(NULL,
139 0,
140 (LPTHREAD_START_ROUTINE)RpcThreadRoutine,
141 NULL,
142 0,
143 NULL);
144 if (!hThread)
145 {
146 ERR("Can't create PortThread\n");
147 return GetLastError();
148 }
149
150 CloseHandle(hThread);
151
152 return ERROR_SUCCESS;
153 }
154
155
156 VOID WINAPI
157 SchedServiceMain(DWORD argc, LPTSTR *argv)
158 {
159 DWORD dwError;
160
161 UNREFERENCED_PARAMETER(argc);
162 UNREFERENCED_PARAMETER(argv);
163
164 TRACE("SchedServiceMain() called\n");
165
166 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
167 ServiceControlHandler,
168 NULL);
169 if (!ServiceStatusHandle)
170 {
171 ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
172 return;
173 }
174
175 UpdateServiceStatus(SERVICE_START_PENDING);
176
177 dwError = ServiceInit();
178 if (dwError != ERROR_SUCCESS)
179 {
180 ERR("Service stopped (dwError: %lu\n", dwError);
181 UpdateServiceStatus(SERVICE_STOPPED);
182 return;
183 }
184
185 UpdateServiceStatus(SERVICE_RUNNING);
186 }
187
188
189 BOOL WINAPI
190 DllMain(HINSTANCE hinstDLL,
191 DWORD fdwReason,
192 LPVOID lpvReserved)
193 {
194 switch (fdwReason)
195 {
196 case DLL_PROCESS_ATTACH:
197 DisableThreadLibraryCalls(hinstDLL);
198 break;
199
200 case DLL_PROCESS_DETACH:
201 break;
202 }
203
204 return TRUE;
205 }