vbscript: Implemented Tan.
[wine.git] / dlls / schedsvc / svc_main.c
blob8c451c9c8c677e41d28d647f85f2d412585944f6
1 /*
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winsvc.h"
26 #include "rpc.h"
27 #include "schrpc.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(schedsvc);
32 static const WCHAR scheduleW[] = {'S','c','h','e','d','u','l','e',0};
33 static SERVICE_STATUS_HANDLE schedsvc_handle;
34 static HANDLE done_event;
36 void schedsvc_auto_start(void)
38 static DWORD start_type;
39 SC_HANDLE scm, service;
40 QUERY_SERVICE_CONFIGW *cfg;
41 DWORD cfg_size;
43 if (start_type == SERVICE_AUTO_START) return;
45 TRACE("changing service start type to SERVICE_AUTO_START\n");
47 scm = OpenSCManagerW(NULL, NULL, 0);
48 if (!scm)
50 WARN("failed to open SCM (%u)\n", GetLastError());
51 return;
54 service = OpenServiceW(scm, scheduleW, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
55 if (service)
57 if (!QueryServiceConfigW(service, NULL, 0, &cfg_size) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
59 cfg = HeapAlloc(GetProcessHeap(), 0, cfg_size);
60 if (cfg)
62 if (QueryServiceConfigW(service, cfg, cfg_size, &cfg_size))
64 start_type = cfg->dwStartType;
65 if (start_type != SERVICE_AUTO_START)
67 if (ChangeServiceConfigW(service, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
68 NULL, NULL, NULL, NULL, NULL, NULL, NULL))
69 start_type = SERVICE_AUTO_START;
72 HeapFree(GetProcessHeap(), 0, cfg);
75 else
76 WARN("failed to query service config (%u)\n", GetLastError());
78 CloseServiceHandle(service);
80 else
81 WARN("failed to open service (%u)\n", GetLastError());
83 CloseServiceHandle(scm);
86 static void schedsvc_update_status(DWORD state)
88 SERVICE_STATUS status;
90 status.dwServiceType = SERVICE_WIN32;
91 status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
92 status.dwWin32ExitCode = 0;
93 status.dwServiceSpecificExitCode = 0;
94 status.dwCheckPoint = 0;
95 status.dwWaitHint = 0;
96 status.dwControlsAccepted = 0;
97 status.dwCurrentState = state;
99 SetServiceStatus(schedsvc_handle, &status);
102 static void WINAPI schedsvc_handler(DWORD control)
104 TRACE("%#x\n", control);
106 switch (control)
108 case SERVICE_CONTROL_STOP:
109 case SERVICE_CONTROL_SHUTDOWN:
110 schedsvc_update_status(SERVICE_STOP_PENDING);
111 SetEvent(done_event);
112 break;
114 default:
115 schedsvc_update_status(SERVICE_RUNNING);
116 break;
120 static RPC_BINDING_VECTOR *sched_bindings;
122 static RPC_STATUS RPC_init(void)
124 WCHAR transport[] = SCHEDSVC_TRANSPORT;
125 RPC_STATUS status;
127 TRACE("using %s\n", debugstr_w(transport));
129 status = RpcServerUseProtseqEpW(transport, 0, NULL, NULL);
130 if (status != RPC_S_OK)
132 WINE_ERR("RpcServerUseProtseqEp error %#x\n", status);
133 return status;
136 status = RpcServerRegisterIf(ITaskSchedulerService_v1_0_s_ifspec, 0, 0);
137 if (status != RPC_S_OK)
139 WINE_ERR("RpcServerRegisterIf error %#x\n", status);
140 return status;
143 status = RpcServerInqBindings(&sched_bindings);
144 if (status != RPC_S_OK)
146 WINE_ERR("RpcServerInqBindings error %#x\n", status);
147 return status;
150 status = RpcEpRegisterW(ITaskSchedulerService_v1_0_s_ifspec, sched_bindings, NULL, NULL);
151 if (status != RPC_S_OK)
153 WINE_ERR("RpcEpRegister error %#x\n", status);
154 return status;
157 status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
158 if (status != RPC_S_OK)
160 WINE_ERR("RpcServerListen error %#x\n", status);
161 return status;
163 return RPC_S_OK;
166 static void RPC_finish(void)
168 RpcMgmtStopServerListening(NULL);
169 RpcEpUnregister(ITaskSchedulerService_v1_0_s_ifspec, sched_bindings, NULL);
170 RpcBindingVectorFree(&sched_bindings);
171 RpcServerUnregisterIf(NULL, NULL, FALSE);
174 void WINAPI ServiceMain(DWORD argc, LPWSTR *argv)
176 TRACE("starting Task Scheduler Service\n");
178 if (RPC_init() != RPC_S_OK) return;
180 schedsvc_handle = RegisterServiceCtrlHandlerW(scheduleW, schedsvc_handler);
181 if (!schedsvc_handle)
183 WINE_ERR("RegisterServiceCtrlHandler error %d\n", GetLastError());
184 return;
187 done_event = CreateEventW(NULL, TRUE, FALSE, NULL);
189 schedsvc_update_status(SERVICE_RUNNING);
191 WaitForSingleObject(done_event, INFINITE);
193 RPC_finish();
194 schedsvc_update_status(SERVICE_STOPPED);
196 TRACE("exiting Task Scheduler Service\n");
199 void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
201 return HeapAlloc(GetProcessHeap(), 0, len);
204 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
206 HeapFree(GetProcessHeap(), 0, ptr);