3 * Copyright (C) 2015 ReactOS Team
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.
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.
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.
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>
27 /* INCLUDES *****************************************************************/
31 WINE_DEFAULT_DEBUG_CHANNEL(schedsvc
);
33 /* GLOBALS ******************************************************************/
35 static WCHAR ServiceName
[] = L
"Schedule";
37 static SERVICE_STATUS_HANDLE ServiceStatusHandle
;
38 static SERVICE_STATUS ServiceStatus
;
40 HANDLE Events
[2] = {NULL
, NULL
}; // StopEvent, UpdateEvent
43 /* FUNCTIONS *****************************************************************/
46 UpdateServiceStatus(DWORD dwState
)
48 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
49 ServiceStatus
.dwCurrentState
= dwState
;
51 if (dwState
== SERVICE_PAUSED
|| dwState
== SERVICE_RUNNING
)
52 ServiceStatus
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
|
53 SERVICE_ACCEPT_SHUTDOWN
|
54 SERVICE_ACCEPT_PAUSE_CONTINUE
;
56 ServiceStatus
.dwControlsAccepted
= 0;
58 ServiceStatus
.dwWin32ExitCode
= 0;
59 ServiceStatus
.dwServiceSpecificExitCode
= 0;
60 ServiceStatus
.dwCheckPoint
= 0;
62 if (dwState
== SERVICE_START_PENDING
||
63 dwState
== SERVICE_STOP_PENDING
||
64 dwState
== SERVICE_PAUSE_PENDING
||
65 dwState
== SERVICE_CONTINUE_PENDING
)
66 ServiceStatus
.dwWaitHint
= 10000;
68 ServiceStatus
.dwWaitHint
= 0;
70 SetServiceStatus(ServiceStatusHandle
,
76 ServiceControlHandler(DWORD dwControl
,
81 TRACE("ServiceControlHandler()\n");
85 case SERVICE_CONTROL_STOP
:
86 case SERVICE_CONTROL_SHUTDOWN
:
87 TRACE(" SERVICE_CONTROL_STOP/SERVICE_CONTROL_SHUTDOWN received\n");
88 UpdateServiceStatus(SERVICE_STOP_PENDING
);
89 /* Stop listening to incoming RPC messages */
90 RpcMgmtStopServerListening(NULL
);
91 if (Events
[0] != NULL
)
95 case SERVICE_CONTROL_PAUSE
:
96 TRACE(" SERVICE_CONTROL_PAUSE received\n");
97 UpdateServiceStatus(SERVICE_PAUSED
);
100 case SERVICE_CONTROL_CONTINUE
:
101 TRACE(" SERVICE_CONTROL_CONTINUE received\n");
102 UpdateServiceStatus(SERVICE_RUNNING
);
103 return ERROR_SUCCESS
;
105 case SERVICE_CONTROL_INTERROGATE
:
106 TRACE(" SERVICE_CONTROL_INTERROGATE received\n");
107 SetServiceStatus(ServiceStatusHandle
,
109 return ERROR_SUCCESS
;
113 TRACE(" Start Shell control received\n");
114 return ERROR_SUCCESS
;
117 TRACE(" Logoff control received\n");
118 return ERROR_SUCCESS
;
122 TRACE(" Control %lu received\n", dwControl
);
123 return ERROR_CALL_NOT_IMPLEMENTED
;
135 /* Initialize the job list */
136 InitializeListHead(&JobListHead
);
138 /* Initialize the job list lock */
139 RtlInitializeResource(&JobListLock
);
141 /* Initialize the start list */
142 InitializeListHead(&StartListHead
);
144 /* Initialize the start list lock */
145 RtlInitializeResource(&StartListLock
);
147 /* Load stored jobs from the registry */
148 dwError
= LoadJobs();
149 if (dwError
!= ERROR_SUCCESS
)
152 /* Start the RPC thread */
153 hThread
= CreateThread(NULL
,
155 (LPTHREAD_START_ROUTINE
)RpcThreadRoutine
,
161 ERR("Could not create the RPC thread\n");
162 return GetLastError();
165 CloseHandle(hThread
);
167 /* Create the stop event */
168 Events
[0] = CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
169 if (Events
[0] == NULL
)
171 ERR("Could not create the stop event\n");
172 return GetLastError();
175 /* Create the update event */
176 Events
[1] = CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
177 if (Events
[1] == NULL
)
179 ERR("Could not create the update event\n");
180 CloseHandle(Events
[0]);
181 return GetLastError();
184 return ERROR_SUCCESS
;
189 SchedServiceMain(DWORD argc
, LPTSTR
*argv
)
191 DWORD dwWait
, dwTimeout
, dwError
;
193 UNREFERENCED_PARAMETER(argc
);
194 UNREFERENCED_PARAMETER(argv
);
196 TRACE("SchedServiceMain()\n");
198 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
199 ServiceControlHandler
,
201 if (!ServiceStatusHandle
)
203 ERR("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
207 UpdateServiceStatus(SERVICE_START_PENDING
);
209 dwError
= ServiceInit();
210 if (dwError
!= ERROR_SUCCESS
)
212 ERR("Service stopped (dwError: %lu\n", dwError
);
213 UpdateServiceStatus(SERVICE_STOPPED
);
217 UpdateServiceStatus(SERVICE_RUNNING
);
219 dwTimeout
= GetNextJobTimeout();
223 /* Wait for the next event */
224 TRACE("Wait for next event!\n");
225 dwWait
= WaitForMultipleObjects(2, Events
, FALSE
, dwTimeout
);
226 if (dwWait
== WAIT_OBJECT_0
)
228 TRACE("Stop event signaled!\n");
231 else if (dwWait
== WAIT_OBJECT_0
+ 1)
233 TRACE("Update event signaled!\n");
234 dwTimeout
= GetNextJobTimeout();
236 else if (dwWait
== WAIT_TIMEOUT
)
238 TRACE("Timeout: Start the next job!\n");
243 /* Close the start and update event handles */
244 CloseHandle(Events
[0]);
245 CloseHandle(Events
[1]);
247 /* Stop the service */
248 UpdateServiceStatus(SERVICE_STOPPED
);
253 DllMain(HINSTANCE hinstDLL
,
259 case DLL_PROCESS_ATTACH
:
260 DisableThreadLibraryCalls(hinstDLL
);
263 case DLL_PROCESS_DETACH
: