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"
30 WINE_DEFAULT_DEBUG_CHANNEL(sc
);
34 const WCHAR
*displayname
;
39 const WCHAR
*password
;
46 static BOOL
parse_create_params( int argc
, const WCHAR
*argv
[], struct create_params
*cp
)
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};
60 cp
->displayname
= NULL
;
61 cp
->type
= SERVICE_WIN32_OWN_PROCESS
;
62 cp
->start
= SERVICE_DEMAND_START
;
63 cp
->error
= SERVICE_ERROR_NORMAL
;
71 for (i
= 0; i
< argc
; i
++)
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];
80 if (!strcmpiW( argv
[i
], tagW
) && i
< argc
- 1)
82 static const WCHAR yesW
[] = {'y','e','s',0};
83 if (!strcmpiW( argv
[i
], yesW
))
85 WINE_FIXME("tag argument not supported\n");
89 if (!strcmpiW( argv
[i
], typeW
) && i
< argc
- 1)
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};
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
;
105 if (!strcmpiW( argv
[i
], startW
) && i
< argc
- 1)
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};
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
;
119 if (!strcmpiW( argv
[i
], errorW
) && i
< argc
- 1)
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};
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
;
132 if (!cp
->binpath
) return FALSE
;
136 static BOOL
parse_failure_actions( const WCHAR
*arg
, SERVICE_FAILURE_ACTIONSW
*fa
)
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
;
144 actions
= HeapAlloc( GetProcessHeap(), 0, (strlenW( arg
) + 1) * sizeof(WCHAR
) );
145 if (!actions
) return FALSE
;
147 strcpyW( actions
, arg
);
148 for (p
= actions
, count
= 0; *p
; p
++)
156 count
= count
/ 2 + 1;
158 fa
->cActions
= count
;
159 fa
->lpsaActions
= HeapAlloc( GetProcessHeap(), 0, fa
->cActions
* sizeof(SC_ACTION
) );
160 if (!fa
->lpsaActions
)
162 HeapFree( GetProcessHeap(), 0, actions
);
167 for (i
= 0; i
< count
; i
++)
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
;
174 p
+= strlenW( p
) + 1;
175 fa
->lpsaActions
[i
].Delay
= atoiW( p
);
176 p
+= strlenW( p
) + 1;
179 HeapFree( GetProcessHeap(), 0, actions
);
183 static BOOL
parse_failure_params( int argc
, const WCHAR
*argv
[], SERVICE_FAILURE_ACTIONSW
*fa
)
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};
191 fa
->dwResetPeriod
= 0;
192 fa
->lpRebootMsg
= NULL
;
193 fa
->lpCommand
= NULL
;
195 fa
->lpsaActions
= NULL
;
197 for (i
= 0; i
< argc
; i
++)
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
))
204 if (i
== argc
- 1) return FALSE
;
205 if (!parse_failure_actions( argv
[i
+ 1], fa
)) return FALSE
;
211 static void usage( void )
213 WINE_MESSAGE( "Usage: sc command servicename [parameter= value ...]\n" );
217 int wmain( int argc
, const WCHAR
*argv
[] )
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
;
229 if (argc
< 3) usage();
231 if (argv
[2][0] == '\\' && argv
[2][1] == '\\')
233 WINE_FIXME("server argument not supported\n");
237 manager
= OpenSCManagerW( NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
240 WINE_ERR("failed to open service manager\n");
244 if (!strcmpiW( argv
[1], createW
))
246 struct create_params cp
;
250 CloseServiceHandle( manager
);
253 if (!parse_create_params( argc
- 3, argv
+ 3, &cp
))
255 WINE_WARN("failed to parse create parameters\n");
256 CloseServiceHandle( manager
);
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
);
264 CloseServiceHandle( service
);
267 else WINE_TRACE("failed to create service %u\n", GetLastError());
269 else if (!strcmpiW( argv
[1], descriptionW
))
271 service
= OpenServiceW( manager
, argv
[2], SERVICE_CHANGE_CONFIG
);
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
);
280 else WINE_TRACE("failed to open service %u\n", GetLastError());
282 else if (!strcmpiW( argv
[1], failureW
))
284 service
= OpenServiceW( manager
, argv
[2], SERVICE_CHANGE_CONFIG
);
287 SERVICE_FAILURE_ACTIONSW sfa
;
288 if (parse_failure_params( argc
- 3, argv
+ 3, &sfa
))
290 ret
= ChangeServiceConfig2W( service
, SERVICE_CONFIG_FAILURE_ACTIONS
, &sfa
);
291 if (!ret
) WINE_TRACE("failed to set service failure actions %u\n", GetLastError());
292 HeapFree( GetProcessHeap(), 0, sfa
.lpsaActions
);
295 WINE_WARN("failed to parse failure parameters\n");
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
);
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
);
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
);
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());
334 WINE_FIXME("command not supported\n");
336 CloseServiceHandle( manager
);