msvcp90: Added setprecision implementation.
[wine] / programs / sc / sc.c
1 /*
2  * Copyright 2010 Hans Leidekker
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #define WIN32_LEAN_AND_MEAN
20
21 #include "wine/debug.h"
22 #include "wine/unicode.h"
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <windows.h>
28 #include <winsvc.h>
29
30 WINE_DEFAULT_DEBUG_CHANNEL(sc);
31
32 struct create_params
33 {
34     const WCHAR *displayname;
35     const WCHAR *binpath;
36     const WCHAR *group;
37     const WCHAR *depend;
38     const WCHAR *obj;
39     const WCHAR *password;
40     DWORD type;
41     DWORD start;
42     DWORD error;
43     BOOL tag;
44 };
45
46 static BOOL parse_create_params( int argc, const WCHAR *argv[], struct create_params *cp )
47 {
48     static const WCHAR displaynameW[] = {'d','i','s','p','l','a','y','n','a','m','e','=',0};
49     static const WCHAR typeW[] = {'t','y','p','e','=',0};
50     static const WCHAR startW[] = {'s','t','a','r','t','=',0};
51     static const WCHAR errorW[] = {'e','r','r','o','r','=',0};
52     static const WCHAR binpathW[] = {'b','i','n','p','a','t','h','=',0};
53     static const WCHAR groupW[] = {'g','r','o','u','p','=',0};
54     static const WCHAR tagW[] = {'t','a','g','=',0};
55     static const WCHAR dependW[] = {'d','e','p','e','n','d','=',0};
56     static const WCHAR objW[] = {'o','b','j','=',0};
57     static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d','=',0};
58     unsigned int i;
59
60     cp->displayname = NULL;
61     cp->type        = SERVICE_WIN32_OWN_PROCESS;
62     cp->start       = SERVICE_DEMAND_START;
63     cp->error       = SERVICE_ERROR_NORMAL;
64     cp->binpath     = NULL;
65     cp->group       = NULL;
66     cp->tag         = FALSE;
67     cp->depend      = NULL;
68     cp->obj         = NULL;
69     cp->password    = NULL;
70
71     for (i = 0; i < argc; i++)
72     {
73         if (!strcmpiW( argv[i], displaynameW ) && i < argc - 1) cp->displayname = argv[i + 1];
74         if (!strcmpiW( argv[i], binpathW ) && i < argc - 1) cp->binpath = argv[i + 1];
75         if (!strcmpiW( argv[i], groupW ) && i < argc - 1) cp->group = argv[i + 1];
76         if (!strcmpiW( argv[i], dependW ) && i < argc - 1) cp->depend = argv[i + 1];
77         if (!strcmpiW( argv[i], objW ) && i < argc - 1) cp->obj = argv[i + 1];
78         if (!strcmpiW( argv[i], passwordW ) && i < argc - 1) cp->password = argv[i + 1];
79
80         if (!strcmpiW( argv[i], tagW ) && i < argc - 1)
81         {
82             static const WCHAR yesW[] = {'y','e','s',0};
83             if (!strcmpiW( argv[i], yesW ))
84             {
85                 WINE_FIXME("tag argument not supported\n");
86                 cp->tag = TRUE;
87             }
88         }
89         if (!strcmpiW( argv[i], typeW ) && i < argc - 1)
90         {
91             static const WCHAR ownW[] = {'o','w','n',0};
92             static const WCHAR shareW[] = {'s','h','a','r','e',0};
93             static const WCHAR kernelW[] = {'k','e','r','n','e','l',0};
94             static const WCHAR filesysW[] = {'f','i','l','e','s','y','s',0};
95             static const WCHAR recW[] = {'r','e','c',0};
96             static const WCHAR interactW[] = {'i','n','t','e','r','a','c','t',0};
97
98             if (!strcmpiW( argv[i + 1], ownW )) cp->type = SERVICE_WIN32_OWN_PROCESS;
99             if (!strcmpiW( argv[i + 1], shareW )) cp->type = SERVICE_WIN32_SHARE_PROCESS;
100             if (!strcmpiW( argv[i + 1], kernelW )) cp->type = SERVICE_KERNEL_DRIVER;
101             if (!strcmpiW( argv[i + 1], filesysW )) cp->type = SERVICE_FILE_SYSTEM_DRIVER;
102             if (!strcmpiW( argv[i + 1], recW )) cp->type = SERVICE_RECOGNIZER_DRIVER;
103             if (!strcmpiW( argv[i + 1], interactW )) cp->type |= SERVICE_INTERACTIVE_PROCESS;
104         }
105         if (!strcmpiW( argv[i], startW ) && i < argc - 1)
106         {
107             static const WCHAR bootW[] = {'b','o','o','t',0};
108             static const WCHAR systemW[] = {'s','y','s','t','e','m',0};
109             static const WCHAR autoW[] = {'a','u','t','o',0};
110             static const WCHAR demandW[] = {'d','e','m','a','n','d',0};
111             static const WCHAR disabledW[] = {'d','i','s','a','b','l','e','d',0};
112
113             if (!strcmpiW( argv[i + 1], bootW )) cp->start = SERVICE_BOOT_START;
114             if (!strcmpiW( argv[i + 1], systemW )) cp->start = SERVICE_SYSTEM_START;
115             if (!strcmpiW( argv[i + 1], autoW )) cp->start = SERVICE_AUTO_START;
116             if (!strcmpiW( argv[i + 1], demandW )) cp->start = SERVICE_DEMAND_START;
117             if (!strcmpiW( argv[i + 1], disabledW )) cp->start = SERVICE_DISABLED;
118         }
119         if (!strcmpiW( argv[i], errorW ) && i < argc - 1)
120         {
121             static const WCHAR normalW[] = {'n','o','r','m','a','l',0};
122             static const WCHAR severeW[] = {'s','e','v','e','r','e',0};
123             static const WCHAR criticalW[] = {'c','r','i','t','i','c','a','l',0};
124             static const WCHAR ignoreW[] = {'i','g','n','o','r','e',0};
125
126             if (!strcmpiW( argv[i + 1], normalW )) cp->error = SERVICE_ERROR_NORMAL;
127             if (!strcmpiW( argv[i + 1], severeW )) cp->error = SERVICE_ERROR_SEVERE;
128             if (!strcmpiW( argv[i + 1], criticalW )) cp->error = SERVICE_ERROR_CRITICAL;
129             if (!strcmpiW( argv[i + 1], ignoreW )) cp->error = SERVICE_ERROR_IGNORE;
130         }
131     }
132     if (!cp->binpath) return FALSE;
133     return TRUE;
134 }
135
136 static BOOL parse_failure_actions( const WCHAR *arg, SERVICE_FAILURE_ACTIONSW *fa )
137 {
138     static const WCHAR runW[] = {'r','u','n',0};
139     static const WCHAR restartW[] = {'r','e','s','t','a','r','t',0};
140     static const WCHAR rebootW[] = {'r','e','b','o','o','t',0};
141     unsigned int i, count;
142     WCHAR *actions, *p;
143
144     actions = HeapAlloc( GetProcessHeap(), 0, (strlenW( arg ) + 1) * sizeof(WCHAR) );
145     if (!actions) return FALSE;
146
147     strcpyW( actions, arg );
148     for (p = actions, count = 0; *p; p++)
149     {
150         if (*p == '/')
151         {
152             count++;
153             *p = 0;
154         }
155     }
156     count = count / 2 + 1;
157
158     fa->cActions = count;
159     fa->lpsaActions = HeapAlloc( GetProcessHeap(), 0, fa->cActions * sizeof(SC_ACTION) );
160     if (!fa->lpsaActions)
161     {
162         HeapFree( GetProcessHeap(), 0, actions );
163         return FALSE;
164     }
165
166     p = actions;
167     for (i = 0; i < count; i++)
168     {
169         if (!strcmpiW( p, runW )) fa->lpsaActions[i].Type = SC_ACTION_RUN_COMMAND;
170         else if (!strcmpiW( p, restartW )) fa->lpsaActions[i].Type = SC_ACTION_RESTART;
171         else if (!strcmpiW( p, rebootW )) fa->lpsaActions[i].Type = SC_ACTION_REBOOT;
172         else fa->lpsaActions[i].Type = SC_ACTION_NONE;
173
174         p += strlenW( p ) + 1;
175         fa->lpsaActions[i].Delay = atoiW( p );
176         p += strlenW( p ) + 1;
177     }
178
179     HeapFree( GetProcessHeap(), 0, actions );
180     return TRUE;
181 }
182
183 static BOOL parse_failure_params( int argc, const WCHAR *argv[], SERVICE_FAILURE_ACTIONSW *fa )
184 {
185     static const WCHAR resetW[] = {'r','e','s','e','t','=',0};
186     static const WCHAR rebootW[] = {'r','e','b','o','o','t','=',0};
187     static const WCHAR commandW[] = {'c','o','m','m','a','n','d','=',0};
188     static const WCHAR actionsW[] = {'a','c','t','i','o','n','s','=',0};
189     unsigned int i;
190
191     fa->dwResetPeriod = 0;
192     fa->lpRebootMsg   = NULL;
193     fa->lpCommand     = NULL;
194     fa->cActions      = 0;
195     fa->lpsaActions   = NULL;
196
197     for (i = 0; i < argc; i++)
198     {
199         if (!strcmpiW( argv[i], resetW ) && i < argc - 1) fa->dwResetPeriod = atoiW( argv[i + 1] );
200         if (!strcmpiW( argv[i], rebootW ) && i < argc - 1) fa->lpRebootMsg = (WCHAR *)argv[i + 1];
201         if (!strcmpiW( argv[i], commandW ) && i < argc - 1) fa->lpCommand = (WCHAR *)argv[i + 1];
202         if (!strcmpiW( argv[i], actionsW ))
203         {
204             if (i == argc - 1) return FALSE;
205             if (!parse_failure_actions( argv[i + 1], fa )) return FALSE;
206         }
207     }
208     return TRUE;
209 }
210
211 static void usage( void )
212 {
213     WINE_MESSAGE( "Usage: sc command servicename [parameter= value ...]\n" );
214     exit( 1 );
215 }
216
217 int wmain( int argc, const WCHAR *argv[] )
218 {
219     static const WCHAR createW[] = {'c','r','e','a','t','e',0};
220     static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
221     static const WCHAR failureW[] = {'f','a','i','l','u','r','e',0};
222     static const WCHAR deleteW[] = {'d','e','l','e','t','e',0};
223     static const WCHAR startW[] = {'s','t','a','r','t',0};
224     static const WCHAR stopW[] = {'s','t','o','p',0};
225     SC_HANDLE manager, service;
226     SERVICE_STATUS status;
227     BOOL ret = FALSE;
228
229     if (argc < 3) usage();
230
231     if (argv[2][0] == '\\' && argv[2][1] == '\\')
232     {
233         WINE_FIXME("server argument not supported\n");
234         return 1;
235     }
236
237     manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_ALL_ACCESS );
238     if (!manager)
239     {
240         WINE_ERR("failed to open service manager\n");
241         return 1;
242     }
243
244     if (!strcmpiW( argv[1], createW ))
245     {
246         struct create_params cp;
247
248         if (argc < 4)
249         {
250             CloseServiceHandle( manager );
251             usage();
252         }
253         if (!parse_create_params( argc - 3, argv + 3, &cp ))
254         {
255             WINE_WARN("failed to parse create parameters\n");
256             CloseServiceHandle( manager );
257             return 1;
258         }
259         service = CreateServiceW( manager, argv[2], cp.displayname, SERVICE_ALL_ACCESS,
260                                   cp.type, cp.start, cp.error, cp.binpath, cp.group, NULL,
261                                   cp.depend, cp.obj, cp.password );
262         if (service)
263         {
264             CloseServiceHandle( service );
265             ret = TRUE;
266         }
267         else WINE_TRACE("failed to create service %u\n", GetLastError());
268     }
269     else if (!strcmpiW( argv[1], descriptionW ))
270     {
271         service = OpenServiceW( manager, argv[2], SERVICE_CHANGE_CONFIG );
272         if (service)
273         {
274             SERVICE_DESCRIPTIONW sd;
275             sd.lpDescription = argc > 3 ? (WCHAR *)argv[3] : NULL;
276             ret = ChangeServiceConfig2W( service, SERVICE_CONFIG_DESCRIPTION, &sd );
277             if (!ret) WINE_TRACE("failed to set service description %u\n", GetLastError());
278             CloseServiceHandle( service );
279         }
280         else WINE_TRACE("failed to open service %u\n", GetLastError());
281     }
282     else if (!strcmpiW( argv[1], failureW ))
283     {
284         service = OpenServiceW( manager, argv[2], SERVICE_CHANGE_CONFIG );
285         if (service)
286         {
287             SERVICE_FAILURE_ACTIONSW sfa;
288             if (!parse_failure_params( argc - 3, argv + 3, &sfa ))
289             {
290                 WINE_WARN("failed to parse failure parameters\n");
291                 CloseServiceHandle( manager );
292                 return 1;
293             }
294             ret = ChangeServiceConfig2W( service, SERVICE_CONFIG_FAILURE_ACTIONS, &sfa );
295             if (!ret) WINE_TRACE("failed to set service failure actions %u\n", GetLastError());
296             HeapFree( GetProcessHeap(), 0, sfa.lpsaActions );
297             CloseServiceHandle( service );
298         }
299         else WINE_TRACE("failed to open service %u\n", GetLastError());
300     }
301     else if (!strcmpiW( argv[1], deleteW ))
302     {
303         service = OpenServiceW( manager, argv[2], DELETE );
304         if (service)
305         {
306             ret = DeleteService( service );
307             if (!ret) WINE_TRACE("failed to delete service %u\n", GetLastError());
308             CloseServiceHandle( service );
309         }
310         else WINE_TRACE("failed to open service %u\n", GetLastError());
311     }
312     else if (!strcmpiW( argv[1], startW ))
313     {
314         service = OpenServiceW( manager, argv[2], SERVICE_START );
315         if (service)
316         {
317             ret = StartServiceW( service, argc - 3, argv + 3 );
318             if (!ret) WINE_TRACE("failed to start service %u\n", GetLastError());
319             CloseServiceHandle( service );
320         }
321         else WINE_TRACE("failed to open service %u\n", GetLastError());
322     }
323     else if (!strcmpiW( argv[1], stopW ))
324     {
325         service = OpenServiceW( manager, argv[2], SERVICE_STOP );
326         if (service)
327         {
328             ret = ControlService( service, SERVICE_CONTROL_STOP, &status );
329             if (!ret) WINE_TRACE("failed to stop service %u\n", GetLastError());
330             CloseServiceHandle( service );
331         }
332         else WINE_TRACE("failed to open service %u\n", GetLastError());
333     }
334     else
335         WINE_FIXME("command not supported\n");
336
337     CloseServiceHandle( manager );
338     return !ret;
339 }