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
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(sc
);
32 const WCHAR
*displayname
;
37 const WCHAR
*password
;
44 static BOOL
parse_create_params( int argc
, const WCHAR
*argv
[], struct create_params
*cp
)
48 cp
->displayname
= NULL
;
49 cp
->type
= SERVICE_WIN32_OWN_PROCESS
;
50 cp
->start
= SERVICE_DEMAND_START
;
51 cp
->error
= SERVICE_ERROR_NORMAL
;
59 for (i
= 0; i
< argc
; i
++)
61 if (!wcsicmp( argv
[i
], L
"displayname=" ) && i
< argc
- 1) cp
->displayname
= argv
[i
+ 1];
62 if (!wcsicmp( argv
[i
], L
"binpath=" ) && i
< argc
- 1) cp
->binpath
= argv
[i
+ 1];
63 if (!wcsicmp( argv
[i
], L
"group=" ) && i
< argc
- 1) cp
->group
= argv
[i
+ 1];
64 if (!wcsicmp( argv
[i
], L
"depend=" ) && i
< argc
- 1) cp
->depend
= argv
[i
+ 1];
65 if (!wcsicmp( argv
[i
], L
"obj=" ) && i
< argc
- 1) cp
->obj
= argv
[i
+ 1];
66 if (!wcsicmp( argv
[i
], L
"password=" ) && i
< argc
- 1) cp
->password
= argv
[i
+ 1];
68 if (!wcsicmp( argv
[i
], L
"tag=" ) && i
< argc
- 1)
70 if (!wcsicmp( argv
[i
], L
"yes" ))
72 WINE_FIXME("tag argument not supported\n");
76 if (!wcsicmp( argv
[i
], L
"type=" ) && i
< argc
- 1)
78 if (!wcsicmp( argv
[i
+ 1], L
"own" )) cp
->type
= SERVICE_WIN32_OWN_PROCESS
;
79 if (!wcsicmp( argv
[i
+ 1], L
"share" )) cp
->type
= SERVICE_WIN32_SHARE_PROCESS
;
80 if (!wcsicmp( argv
[i
+ 1], L
"kernel" )) cp
->type
= SERVICE_KERNEL_DRIVER
;
81 if (!wcsicmp( argv
[i
+ 1], L
"filesys" )) cp
->type
= SERVICE_FILE_SYSTEM_DRIVER
;
82 if (!wcsicmp( argv
[i
+ 1], L
"rec" )) cp
->type
= SERVICE_RECOGNIZER_DRIVER
;
83 if (!wcsicmp( argv
[i
+ 1], L
"interact" )) cp
->type
|= SERVICE_INTERACTIVE_PROCESS
;
85 if (!wcsicmp( argv
[i
], L
"start=" ) && i
< argc
- 1)
87 if (!wcsicmp( argv
[i
+ 1], L
"boot" )) cp
->start
= SERVICE_BOOT_START
;
88 if (!wcsicmp( argv
[i
+ 1], L
"system" )) cp
->start
= SERVICE_SYSTEM_START
;
89 if (!wcsicmp( argv
[i
+ 1], L
"auto" )) cp
->start
= SERVICE_AUTO_START
;
90 if (!wcsicmp( argv
[i
+ 1], L
"demand" )) cp
->start
= SERVICE_DEMAND_START
;
91 if (!wcsicmp( argv
[i
+ 1], L
"disabled" )) cp
->start
= SERVICE_DISABLED
;
93 if (!wcsicmp( argv
[i
], L
"error=" ) && i
< argc
- 1)
95 if (!wcsicmp( argv
[i
+ 1], L
"normal" )) cp
->error
= SERVICE_ERROR_NORMAL
;
96 if (!wcsicmp( argv
[i
+ 1], L
"severe" )) cp
->error
= SERVICE_ERROR_SEVERE
;
97 if (!wcsicmp( argv
[i
+ 1], L
"critical" )) cp
->error
= SERVICE_ERROR_CRITICAL
;
98 if (!wcsicmp( argv
[i
+ 1], L
"ignore" )) cp
->error
= SERVICE_ERROR_IGNORE
;
101 if (!cp
->binpath
) return FALSE
;
105 static BOOL
parse_failure_actions( const WCHAR
*arg
, SERVICE_FAILURE_ACTIONSW
*fa
)
107 unsigned int i
, count
;
110 actions
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW( arg
) + 1) * sizeof(WCHAR
) );
111 if (!actions
) return FALSE
;
113 lstrcpyW( actions
, arg
);
114 for (p
= actions
, count
= 0; *p
; p
++)
122 count
= count
/ 2 + 1;
124 fa
->cActions
= count
;
125 fa
->lpsaActions
= HeapAlloc( GetProcessHeap(), 0, fa
->cActions
* sizeof(SC_ACTION
) );
126 if (!fa
->lpsaActions
)
128 HeapFree( GetProcessHeap(), 0, actions
);
133 for (i
= 0; i
< count
; i
++)
135 if (!wcsicmp( p
, L
"run" )) fa
->lpsaActions
[i
].Type
= SC_ACTION_RUN_COMMAND
;
136 else if (!wcsicmp( p
, L
"restart" )) fa
->lpsaActions
[i
].Type
= SC_ACTION_RESTART
;
137 else if (!wcsicmp( p
, L
"reboot" )) fa
->lpsaActions
[i
].Type
= SC_ACTION_REBOOT
;
138 else fa
->lpsaActions
[i
].Type
= SC_ACTION_NONE
;
140 p
+= lstrlenW( p
) + 1;
141 fa
->lpsaActions
[i
].Delay
= wcstol( p
, NULL
, 10 );
142 p
+= lstrlenW( p
) + 1;
145 HeapFree( GetProcessHeap(), 0, actions
);
149 static BOOL
parse_failure_params( int argc
, const WCHAR
*argv
[], SERVICE_FAILURE_ACTIONSW
*fa
)
153 fa
->dwResetPeriod
= 0;
154 fa
->lpRebootMsg
= NULL
;
155 fa
->lpCommand
= NULL
;
157 fa
->lpsaActions
= NULL
;
159 for (i
= 0; i
< argc
; i
++)
161 if (!wcsicmp( argv
[i
], L
"reset=" ) && i
< argc
- 1) fa
->dwResetPeriod
= wcstol( argv
[i
+ 1], NULL
, 10 );
162 if (!wcsicmp( argv
[i
], L
"reboot=" ) && i
< argc
- 1) fa
->lpRebootMsg
= (WCHAR
*)argv
[i
+ 1];
163 if (!wcsicmp( argv
[i
], L
"command=" ) && i
< argc
- 1) fa
->lpCommand
= (WCHAR
*)argv
[i
+ 1];
164 if (!wcsicmp( argv
[i
], L
"actions=" ))
166 if (i
== argc
- 1) return FALSE
;
167 if (!parse_failure_actions( argv
[i
+ 1], fa
)) return FALSE
;
173 static void usage( void )
175 WINE_MESSAGE( "Usage: sc command servicename [parameter= value ...]\n" );
179 int __cdecl
wmain( int argc
, const WCHAR
*argv
[] )
181 SC_HANDLE manager
, service
;
182 SERVICE_STATUS status
;
185 if (argc
< 3) usage();
187 if (argv
[2][0] == '\\' && argv
[2][1] == '\\')
189 WINE_FIXME("server argument not supported\n");
193 manager
= OpenSCManagerW( NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
196 WINE_ERR("failed to open service manager\n");
200 if (!wcsicmp( argv
[1], L
"create" ))
202 struct create_params cp
;
206 CloseServiceHandle( manager
);
209 if (!parse_create_params( argc
- 3, argv
+ 3, &cp
))
211 WINE_WARN("failed to parse create parameters\n");
212 CloseServiceHandle( manager
);
215 service
= CreateServiceW( manager
, argv
[2], cp
.displayname
, SERVICE_ALL_ACCESS
,
216 cp
.type
, cp
.start
, cp
.error
, cp
.binpath
, cp
.group
, NULL
,
217 cp
.depend
, cp
.obj
, cp
.password
);
220 CloseServiceHandle( service
);
223 else WINE_TRACE("failed to create service %u\n", GetLastError());
225 else if (!wcsicmp( argv
[1], L
"description" ))
227 service
= OpenServiceW( manager
, argv
[2], SERVICE_CHANGE_CONFIG
);
230 SERVICE_DESCRIPTIONW sd
;
231 sd
.lpDescription
= argc
> 3 ? (WCHAR
*)argv
[3] : NULL
;
232 ret
= ChangeServiceConfig2W( service
, SERVICE_CONFIG_DESCRIPTION
, &sd
);
233 if (!ret
) WINE_TRACE("failed to set service description %u\n", GetLastError());
234 CloseServiceHandle( service
);
236 else WINE_TRACE("failed to open service %u\n", GetLastError());
238 else if (!wcsicmp( argv
[1], L
"failure" ))
240 service
= OpenServiceW( manager
, argv
[2], SERVICE_CHANGE_CONFIG
);
243 SERVICE_FAILURE_ACTIONSW sfa
;
244 if (parse_failure_params( argc
- 3, argv
+ 3, &sfa
))
246 ret
= ChangeServiceConfig2W( service
, SERVICE_CONFIG_FAILURE_ACTIONS
, &sfa
);
247 if (!ret
) WINE_TRACE("failed to set service failure actions %u\n", GetLastError());
248 HeapFree( GetProcessHeap(), 0, sfa
.lpsaActions
);
251 WINE_WARN("failed to parse failure parameters\n");
252 CloseServiceHandle( service
);
254 else WINE_TRACE("failed to open service %u\n", GetLastError());
256 else if (!wcsicmp( argv
[1], L
"delete" ))
258 service
= OpenServiceW( manager
, argv
[2], DELETE
);
261 ret
= DeleteService( service
);
262 if (!ret
) WINE_TRACE("failed to delete service %u\n", GetLastError());
263 CloseServiceHandle( service
);
265 else WINE_TRACE("failed to open service %u\n", GetLastError());
267 else if (!wcsicmp( argv
[1], L
"start" ))
269 service
= OpenServiceW( manager
, argv
[2], SERVICE_START
);
272 ret
= StartServiceW( service
, argc
- 3, argv
+ 3 );
273 if (!ret
) WINE_TRACE("failed to start service %u\n", GetLastError());
274 CloseServiceHandle( service
);
276 else WINE_TRACE("failed to open service %u\n", GetLastError());
278 else if (!wcsicmp( argv
[1], L
"stop" ))
280 service
= OpenServiceW( manager
, argv
[2], SERVICE_STOP
);
283 ret
= ControlService( service
, SERVICE_CONTROL_STOP
, &status
);
284 if (!ret
) WINE_TRACE("failed to stop service %u\n", GetLastError());
285 CloseServiceHandle( service
);
287 else WINE_TRACE("failed to open service %u\n", GetLastError());
289 else if (!wcsicmp( argv
[1], L
"sdset" ))
291 WINE_FIXME("SdSet command not supported, faking success\n");
295 WINE_FIXME("command not supported\n");
297 CloseServiceHandle( manager
);