Release 1.3.2.
[wine/gsoc-2012-control.git] / programs / sc / sc.c
blobe4df09affbdb3191200a47e4f925d127692c0ba7
1 /*
2 * Copyright 2010 Hans Leidekker
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define WIN32_LEAN_AND_MEAN
21 #include "wine/debug.h"
22 #include "wine/unicode.h"
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <windows.h>
29 WINE_DEFAULT_DEBUG_CHANNEL(sc);
31 struct create_params
33 const WCHAR *displayname;
34 const WCHAR *binpath;
35 const WCHAR *group;
36 const WCHAR *depend;
37 const WCHAR *obj;
38 const WCHAR *password;
39 DWORD type;
40 DWORD start;
41 DWORD error;
42 BOOL tag;
45 static BOOL parse_create_params( int argc, const WCHAR *argv[], struct create_params *cp )
47 static const WCHAR displaynameW[] = {'d','i','s','p','l','a','y','n','a','m','e','=',0};
48 static const WCHAR typeW[] = {'t','y','p','e','=',0};
49 static const WCHAR startW[] = {'s','t','a','r','t','=',0};
50 static const WCHAR errorW[] = {'e','r','r','o','r','=',0};
51 static const WCHAR binpathW[] = {'b','i','n','p','a','t','h','=',0};
52 static const WCHAR groupW[] = {'g','r','o','u','p','=',0};
53 static const WCHAR tagW[] = {'t','a','g','=',0};
54 static const WCHAR dependW[] = {'d','e','p','e','n','d','=',0};
55 static const WCHAR objW[] = {'o','b','j','=',0};
56 static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d','=',0};
57 unsigned int i;
59 cp->displayname = NULL;
60 cp->type = SERVICE_WIN32_OWN_PROCESS;
61 cp->start = SERVICE_DEMAND_START;
62 cp->error = SERVICE_ERROR_NORMAL;
63 cp->binpath = NULL;
64 cp->group = NULL;
65 cp->tag = FALSE;
66 cp->depend = NULL;
67 cp->obj = NULL;
68 cp->password = NULL;
70 for (i = 0; i < argc; i++)
72 if (!strcmpiW( argv[i], displaynameW ) && i < argc - 1) cp->displayname = argv[i + 1];
73 if (!strcmpiW( argv[i], binpathW ) && i < argc - 1) cp->binpath = argv[i + 1];
74 if (!strcmpiW( argv[i], groupW ) && i < argc - 1) cp->group = argv[i + 1];
75 if (!strcmpiW( argv[i], dependW ) && i < argc - 1) cp->depend = argv[i + 1];
76 if (!strcmpiW( argv[i], objW ) && i < argc - 1) cp->obj = argv[i + 1];
77 if (!strcmpiW( argv[i], passwordW ) && i < argc - 1) cp->password = argv[i + 1];
79 if (!strcmpiW( argv[i], tagW ) && i < argc - 1)
81 static const WCHAR yesW[] = {'y','e','s',0};
82 if (!strcmpiW( argv[i], yesW ))
84 WINE_FIXME("tag argument not supported\n");
85 cp->tag = TRUE;
88 if (!strcmpiW( argv[i], typeW ) && i < argc - 1)
90 static const WCHAR ownW[] = {'o','w','n',0};
91 static const WCHAR shareW[] = {'s','h','a','r','e',0};
92 static const WCHAR kernelW[] = {'k','e','r','n','e','l',0};
93 static const WCHAR filesysW[] = {'f','i','l','e','s','y','s',0};
94 static const WCHAR recW[] = {'r','e','c',0};
95 static const WCHAR interactW[] = {'i','n','t','e','r','a','c','t',0};
97 if (!strcmpiW( argv[i + 1], ownW )) cp->type = SERVICE_WIN32_OWN_PROCESS;
98 if (!strcmpiW( argv[i + 1], shareW )) cp->type = SERVICE_WIN32_SHARE_PROCESS;
99 if (!strcmpiW( argv[i + 1], kernelW )) cp->type = SERVICE_KERNEL_DRIVER;
100 if (!strcmpiW( argv[i + 1], filesysW )) cp->type = SERVICE_FILE_SYSTEM_DRIVER;
101 if (!strcmpiW( argv[i + 1], recW )) cp->type = SERVICE_RECOGNIZER_DRIVER;
102 if (!strcmpiW( argv[i + 1], interactW )) cp->type |= SERVICE_INTERACTIVE_PROCESS;
104 if (!strcmpiW( argv[i], startW ) && i < argc - 1)
106 static const WCHAR bootW[] = {'b','o','o','t',0};
107 static const WCHAR systemW[] = {'s','y','s','t','e','m',0};
108 static const WCHAR autoW[] = {'a','u','t','o',0};
109 static const WCHAR demandW[] = {'d','e','m','a','n','d',0};
110 static const WCHAR disabledW[] = {'d','i','s','a','b','l','e','d',0};
112 if (!strcmpiW( argv[i + 1], bootW )) cp->start = SERVICE_BOOT_START;
113 if (!strcmpiW( argv[i + 1], systemW )) cp->start = SERVICE_SYSTEM_START;
114 if (!strcmpiW( argv[i + 1], autoW )) cp->start = SERVICE_AUTO_START;
115 if (!strcmpiW( argv[i + 1], demandW )) cp->start = SERVICE_DEMAND_START;
116 if (!strcmpiW( argv[i + 1], disabledW )) cp->start = SERVICE_DISABLED;
118 if (!strcmpiW( argv[i], errorW ) && i < argc - 1)
120 static const WCHAR normalW[] = {'n','o','r','m','a','l',0};
121 static const WCHAR severeW[] = {'s','e','v','e','r','e',0};
122 static const WCHAR criticalW[] = {'c','r','i','t','i','c','a','l',0};
123 static const WCHAR ignoreW[] = {'i','g','n','o','r','e',0};
125 if (!strcmpiW( argv[i + 1], normalW )) cp->error = SERVICE_ERROR_NORMAL;
126 if (!strcmpiW( argv[i + 1], severeW )) cp->error = SERVICE_ERROR_SEVERE;
127 if (!strcmpiW( argv[i + 1], criticalW )) cp->error = SERVICE_ERROR_CRITICAL;
128 if (!strcmpiW( argv[i + 1], ignoreW )) cp->error = SERVICE_ERROR_IGNORE;
131 if (!cp->binpath) return FALSE;
132 return TRUE;
135 static BOOL parse_failure_actions( const WCHAR *arg, SERVICE_FAILURE_ACTIONSW *fa )
137 static const WCHAR runW[] = {'r','u','n',0};
138 static const WCHAR restartW[] = {'r','e','s','t','a','r','t',0};
139 static const WCHAR rebootW[] = {'r','e','b','o','o','t',0};
140 unsigned int i, count;
141 WCHAR *actions, *p;
143 actions = HeapAlloc( GetProcessHeap(), 0, (strlenW( arg ) + 1) * sizeof(WCHAR) );
144 if (!actions) return FALSE;
146 strcpyW( actions, arg );
147 for (p = actions, count = 0; *p; p++)
149 if (*p == '/')
151 count++;
152 *p = 0;
155 count = count / 2 + 1;
157 fa->cActions = count;
158 fa->lpsaActions = HeapAlloc( GetProcessHeap(), 0, fa->cActions * sizeof(SC_ACTION) );
159 if (!fa->lpsaActions)
161 HeapFree( GetProcessHeap(), 0, actions );
162 return FALSE;
165 p = actions;
166 for (i = 0; i < count; i++)
168 if (!strcmpiW( p, runW )) fa->lpsaActions[i].Type = SC_ACTION_RUN_COMMAND;
169 else if (!strcmpiW( p, restartW )) fa->lpsaActions[i].Type = SC_ACTION_RESTART;
170 else if (!strcmpiW( p, rebootW )) fa->lpsaActions[i].Type = SC_ACTION_REBOOT;
171 else fa->lpsaActions[i].Type = SC_ACTION_NONE;
173 p += strlenW( p ) + 1;
174 fa->lpsaActions[i].Delay = atoiW( p );
175 p += strlenW( p ) + 1;
178 HeapFree( GetProcessHeap(), 0, actions );
179 return TRUE;
182 static BOOL parse_failure_params( int argc, const WCHAR *argv[], SERVICE_FAILURE_ACTIONSW *fa )
184 static const WCHAR resetW[] = {'r','e','s','e','t','=',0};
185 static const WCHAR rebootW[] = {'r','e','b','o','o','t','=',0};
186 static const WCHAR commandW[] = {'c','o','m','m','a','n','d','=',0};
187 static const WCHAR actionsW[] = {'a','c','t','i','o','n','s','=',0};
188 unsigned int i;
190 fa->dwResetPeriod = 0;
191 fa->lpRebootMsg = NULL;
192 fa->lpCommand = NULL;
193 fa->cActions = 0;
194 fa->lpsaActions = NULL;
196 for (i = 0; i < argc; i++)
198 if (!strcmpiW( argv[i], resetW ) && i < argc - 1) fa->dwResetPeriod = atoiW( argv[i + 1] );
199 if (!strcmpiW( argv[i], rebootW ) && i < argc - 1) fa->lpRebootMsg = (WCHAR *)argv[i + 1];
200 if (!strcmpiW( argv[i], commandW ) && i < argc - 1) fa->lpCommand = (WCHAR *)argv[i + 1];
201 if (!strcmpiW( argv[i], actionsW ))
203 if (i == argc - 1) return FALSE;
204 if (!parse_failure_actions( argv[i + 1], fa )) return FALSE;
207 return TRUE;
210 static void usage( void )
212 WINE_MESSAGE( "Usage: sc command servicename [parameter= value ...]\n" );
213 exit( 1 );
216 int wmain( int argc, const WCHAR *argv[] )
218 static const WCHAR createW[] = {'c','r','e','a','t','e',0};
219 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
220 static const WCHAR failureW[] = {'f','a','i','l','u','r','e',0};
221 static const WCHAR deleteW[] = {'d','e','l','e','t','e',0};
222 static const WCHAR startW[] = {'s','t','a','r','t',0};
223 static const WCHAR stopW[] = {'s','t','o','p',0};
224 SC_HANDLE manager, service;
225 SERVICE_STATUS status;
226 BOOL ret = FALSE;
228 if (argc < 3) usage();
230 if (argv[2][0] == '\\' && argv[2][1] == '\\')
232 WINE_FIXME("server argument not supported\n");
233 return 1;
236 manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_ALL_ACCESS );
237 if (!manager)
239 WINE_ERR("failed to open service manager\n");
240 return 1;
243 if (!strcmpiW( argv[1], createW ))
245 struct create_params cp;
247 if (argc < 4)
249 CloseServiceHandle( manager );
250 usage();
252 if (!parse_create_params( argc - 3, argv + 3, &cp ))
254 WINE_WARN("failed to parse create parameters\n");
255 CloseServiceHandle( manager );
256 return 1;
258 service = CreateServiceW( manager, argv[2], cp.displayname, SERVICE_ALL_ACCESS,
259 cp.type, cp.start, cp.error, cp.binpath, cp.group, NULL,
260 cp.depend, cp.obj, cp.password );
261 if (service)
263 CloseServiceHandle( service );
264 ret = TRUE;
266 else WINE_TRACE("failed to create service %u\n", GetLastError());
268 else if (!strcmpiW( argv[1], descriptionW ))
270 service = OpenServiceW( manager, argv[2], SERVICE_CHANGE_CONFIG );
271 if (service)
273 SERVICE_DESCRIPTIONW sd;
274 sd.lpDescription = argc > 3 ? (WCHAR *)argv[3] : NULL;
275 ret = ChangeServiceConfig2W( service, SERVICE_CONFIG_DESCRIPTION, &sd );
276 if (!ret) WINE_TRACE("failed to set service description %u\n", GetLastError());
277 CloseServiceHandle( service );
279 else WINE_TRACE("failed to open service %u\n", GetLastError());
281 else if (!strcmpiW( argv[1], failureW ))
283 service = OpenServiceW( manager, argv[2], SERVICE_CHANGE_CONFIG );
284 if (service)
286 SERVICE_FAILURE_ACTIONSW sfa;
287 if (!parse_failure_params( argc - 3, argv + 3, &sfa ))
289 WINE_WARN("failed to parse failure parameters\n");
290 CloseServiceHandle( manager );
291 return 1;
293 ret = ChangeServiceConfig2W( service, SERVICE_CONFIG_FAILURE_ACTIONS, &sfa );
294 if (!ret) WINE_TRACE("failed to set service failure actions %u\n", GetLastError());
295 HeapFree( GetProcessHeap(), 0, sfa.lpsaActions );
296 CloseServiceHandle( service );
298 else WINE_TRACE("failed to open service %u\n", GetLastError());
300 else if (!strcmpiW( argv[1], deleteW ))
302 service = OpenServiceW( manager, argv[2], DELETE );
303 if (service)
305 ret = DeleteService( service );
306 if (!ret) WINE_TRACE("failed to delete service %u\n", GetLastError());
307 CloseServiceHandle( service );
309 else WINE_TRACE("failed to open service %u\n", GetLastError());
311 else if (!strcmpiW( argv[1], startW ))
313 service = OpenServiceW( manager, argv[2], SERVICE_START );
314 if (service)
316 ret = StartServiceW( service, argc - 3, argv + 3 );
317 if (!ret) WINE_TRACE("failed to start service %u\n", GetLastError());
318 CloseServiceHandle( service );
320 else WINE_TRACE("failed to open service %u\n", GetLastError());
322 else if (!strcmpiW( argv[1], stopW ))
324 service = OpenServiceW( manager, argv[2], SERVICE_STOP );
325 if (service)
327 ret = ControlService( service, SERVICE_CONTROL_STOP, &status );
328 if (!ret) WINE_TRACE("failed to stop service %u\n", GetLastError());
329 CloseServiceHandle( service );
331 else WINE_TRACE("failed to open service %u\n", GetLastError());
333 else
334 WINE_FIXME("command not supported\n");
336 CloseServiceHandle( manager );
337 return !ret;