2 * Task Scheduler Service
4 * Copyright 2014 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
30 #include "schedsvc_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(schedsvc
);
34 static const WCHAR scheduleW
[] = {'S','c','h','e','d','u','l','e',0};
35 static SERVICE_STATUS_HANDLE schedsvc_handle
;
36 static HANDLE done_event
;
38 void schedsvc_auto_start(void)
40 static DWORD start_type
;
41 SC_HANDLE scm
, service
;
42 QUERY_SERVICE_CONFIGW
*cfg
;
45 if (start_type
== SERVICE_AUTO_START
) return;
47 TRACE("changing service start type to SERVICE_AUTO_START\n");
49 scm
= OpenSCManagerW(NULL
, NULL
, 0);
52 WARN("failed to open SCM (%u)\n", GetLastError());
56 service
= OpenServiceW(scm
, scheduleW
, SERVICE_QUERY_CONFIG
| SERVICE_CHANGE_CONFIG
);
59 if (!QueryServiceConfigW(service
, NULL
, 0, &cfg_size
) && GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
61 cfg
= HeapAlloc(GetProcessHeap(), 0, cfg_size
);
64 if (QueryServiceConfigW(service
, cfg
, cfg_size
, &cfg_size
))
66 start_type
= cfg
->dwStartType
;
67 if (start_type
!= SERVICE_AUTO_START
)
69 if (ChangeServiceConfigW(service
, SERVICE_NO_CHANGE
, SERVICE_AUTO_START
, SERVICE_NO_CHANGE
,
70 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
))
71 start_type
= SERVICE_AUTO_START
;
74 HeapFree(GetProcessHeap(), 0, cfg
);
78 WARN("failed to query service config (%u)\n", GetLastError());
80 CloseServiceHandle(service
);
83 WARN("failed to open service (%u)\n", GetLastError());
85 CloseServiceHandle(scm
);
88 static void schedsvc_update_status(DWORD state
)
90 SERVICE_STATUS status
;
92 status
.dwServiceType
= SERVICE_WIN32
;
93 status
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
;
94 status
.dwWin32ExitCode
= 0;
95 status
.dwServiceSpecificExitCode
= 0;
96 status
.dwCheckPoint
= 0;
97 status
.dwWaitHint
= 0;
98 status
.dwControlsAccepted
= 0;
99 status
.dwCurrentState
= state
;
101 SetServiceStatus(schedsvc_handle
, &status
);
104 static void WINAPI
schedsvc_handler(DWORD control
)
106 TRACE("%#x\n", control
);
110 case SERVICE_CONTROL_STOP
:
111 case SERVICE_CONTROL_SHUTDOWN
:
112 schedsvc_update_status(SERVICE_STOP_PENDING
);
113 SetEvent(done_event
);
117 schedsvc_update_status(SERVICE_RUNNING
);
122 static RPC_BINDING_VECTOR
*sched_bindings
;
124 static RPC_STATUS
RPC_init(void)
126 WCHAR transport
[] = SCHEDSVC_TRANSPORT
;
129 TRACE("using %s\n", debugstr_w(transport
));
131 status
= RpcServerUseProtseqEpW(transport
, 0, NULL
, NULL
);
132 if (status
!= RPC_S_OK
)
134 ERR("RpcServerUseProtseqEp error %#x\n", status
);
138 status
= RpcServerRegisterIf(ITaskSchedulerService_v1_0_s_ifspec
, 0, 0);
139 if (status
!= RPC_S_OK
)
141 ERR("RpcServerRegisterIf error %#x\n", status
);
145 status
= RpcServerInqBindings(&sched_bindings
);
146 if (status
!= RPC_S_OK
)
148 ERR("RpcServerInqBindings error %#x\n", status
);
152 status
= RpcEpRegisterW(ITaskSchedulerService_v1_0_s_ifspec
, sched_bindings
, NULL
, NULL
);
153 if (status
!= RPC_S_OK
)
155 ERR("RpcEpRegister error %#x\n", status
);
159 status
= RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT
, TRUE
);
160 if (status
!= RPC_S_OK
)
162 ERR("RpcServerListen error %#x\n", status
);
168 static void RPC_finish(void)
170 RpcMgmtStopServerListening(NULL
);
171 RpcEpUnregister(ITaskSchedulerService_v1_0_s_ifspec
, sched_bindings
, NULL
);
172 RpcBindingVectorFree(&sched_bindings
);
173 RpcServerUnregisterIf(NULL
, NULL
, FALSE
);
176 void WINAPI
ServiceMain(DWORD argc
, LPWSTR
*argv
)
178 TRACE("starting Task Scheduler Service\n");
180 schedsvc_handle
= RegisterServiceCtrlHandlerW(scheduleW
, schedsvc_handler
);
181 if (!schedsvc_handle
)
183 ERR("RegisterServiceCtrlHandler error %d\n", GetLastError());
187 done_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
189 schedsvc_update_status(SERVICE_START_PENDING
);
191 if (RPC_init() == RPC_S_OK
)
193 schedsvc_update_status(SERVICE_RUNNING
);
194 WaitForSingleObject(done_event
, INFINITE
);
198 schedsvc_update_status(SERVICE_STOPPED
);
200 TRACE("exiting Task Scheduler Service\n");
203 void __RPC_FAR
* __RPC_USER
MIDL_user_allocate(SIZE_T len
)
205 return heap_alloc(len
);
208 void __RPC_USER
MIDL_user_free(void __RPC_FAR
* ptr
)