r23779: Change from v2 or later to v3 or later.
[jra/samba/.git] / source3 / utils / net_rpc_service.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) Gerald (Jerry) Carter          2005
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program 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
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19  
20 #include "includes.h"
21 #include "utils/net.h"
22
23
24 /********************************************************************
25 ********************************************************************/
26
27 static WERROR query_service_state(struct rpc_pipe_client *pipe_hnd,
28                                 TALLOC_CTX *mem_ctx, 
29                                 POLICY_HND *hSCM,
30                                 const char *service,
31                                 uint32 *state )
32 {
33         POLICY_HND hService;
34         SERVICE_STATUS service_status;
35         WERROR result = WERR_GENERAL_FAILURE;
36         
37         /* now cycle until the status is actually 'watch_state' */
38         
39         result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, hSCM, &hService, 
40                 service, SC_RIGHT_SVC_QUERY_STATUS );
41
42         if ( !W_ERROR_IS_OK(result) ) {
43                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
44                 return result;
45         }
46
47         result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status  );
48         if ( W_ERROR_IS_OK(result) ) {
49                 *state = service_status.state;
50         }
51         
52         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService);
53         
54         return result;
55 }
56
57 /********************************************************************
58 ********************************************************************/
59
60 static WERROR watch_service_state(struct rpc_pipe_client *pipe_hnd,
61                                 TALLOC_CTX *mem_ctx, 
62                                 POLICY_HND *hSCM,
63                                 const char *service, 
64                                 uint32 watch_state,
65                                 uint32 *final_state )
66 {
67         uint32 i;
68         uint32 state = 0;
69         WERROR result = WERR_GENERAL_FAILURE;
70         
71         
72         i = 0;
73         while ( (state != watch_state ) && i<30 ) {
74                 /* get the status */
75
76                 result = query_service_state(pipe_hnd, mem_ctx, hSCM, service, &state  );
77                 if ( !W_ERROR_IS_OK(result) ) {
78                         break;
79                 }
80                 
81                 d_printf(".");
82                 i++;
83                 sys_usleep( 100 );
84         }
85         d_printf("\n");
86         
87         *final_state = state;
88         
89         return result;
90 }
91
92 /********************************************************************
93 ********************************************************************/
94
95 static WERROR control_service(struct rpc_pipe_client *pipe_hnd,
96                                 TALLOC_CTX *mem_ctx, 
97                                 POLICY_HND *hSCM,
98                                 const char *service, 
99                                 uint32 control,
100                                 uint32 watch_state )
101 {
102         POLICY_HND hService;
103         WERROR result = WERR_GENERAL_FAILURE;
104         SERVICE_STATUS service_status;
105         uint32 state = 0;
106         
107         /* Open the Service */
108         
109         result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, hSCM, &hService, 
110                 service, (SC_RIGHT_SVC_STOP|SC_RIGHT_SVC_PAUSE_CONTINUE) );
111
112         if ( !W_ERROR_IS_OK(result) ) {
113                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
114                 goto done;
115         }
116         
117         /* get the status */
118
119         result = rpccli_svcctl_control_service(pipe_hnd, mem_ctx, &hService, 
120                 control, &service_status  );
121                 
122         if ( !W_ERROR_IS_OK(result) ) {
123                 d_fprintf(stderr, "Control service request failed.  [%s]\n", dos_errstr(result));
124                 goto done;
125         }
126         
127         /* loop -- checking the state until we are where we want to be */
128         
129         result = watch_service_state(pipe_hnd, mem_ctx, hSCM, service, watch_state, &state );
130                 
131         d_printf("%s service is %s.\n", service, svc_status_string(state));
132
133 done:   
134         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService);
135                 
136         return result;
137 }       
138
139 /********************************************************************
140 ********************************************************************/
141
142 static NTSTATUS rpc_service_list_internal(const DOM_SID *domain_sid,
143                                         const char *domain_name, 
144                                         struct cli_state *cli,
145                                         struct rpc_pipe_client *pipe_hnd,
146                                         TALLOC_CTX *mem_ctx, 
147                                         int argc,
148                                         const char **argv )
149 {
150         POLICY_HND hSCM;
151         ENUM_SERVICES_STATUS *services;
152         WERROR result = WERR_GENERAL_FAILURE;
153         fstring servicename;
154         fstring displayname;
155         uint32 num_services = 0;
156         int i;
157         
158         if (argc != 0 ) {
159                 d_printf("Usage: net rpc service list\n");
160                 return NT_STATUS_OK;
161         }
162
163         result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
164         if ( !W_ERROR_IS_OK(result) ) {
165                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
166                 return werror_to_ntstatus(result);
167         }
168         
169         result = rpccli_svcctl_enumerate_services(pipe_hnd, mem_ctx, &hSCM, SVCCTL_TYPE_WIN32,
170                 SVCCTL_STATE_ALL, &num_services, &services );
171         
172         if ( !W_ERROR_IS_OK(result) ) {
173                 d_fprintf(stderr, "Failed to enumerate services.  [%s]\n", dos_errstr(result));
174                 goto done;
175         }
176         
177         if ( num_services == 0 )
178                 d_printf("No services returned\n");
179         
180         for ( i=0; i<num_services; i++ ) {
181                 rpcstr_pull( servicename, services[i].servicename.buffer, sizeof(servicename), -1, STR_TERMINATE );
182                 rpcstr_pull( displayname, services[i].displayname.buffer, sizeof(displayname), -1, STR_TERMINATE );
183                 
184                 d_printf("%-20s    \"%s\"\n", servicename, displayname);
185         }
186
187 done:   
188         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM);
189                 
190         return werror_to_ntstatus(result);
191 }       
192
193 /********************************************************************
194 ********************************************************************/
195
196 static NTSTATUS rpc_service_status_internal(const DOM_SID *domain_sid,
197                                                 const char *domain_name, 
198                                                 struct cli_state *cli,
199                                                 struct rpc_pipe_client *pipe_hnd,
200                                                 TALLOC_CTX *mem_ctx, 
201                                                 int argc,
202                                                 const char **argv )
203 {
204         POLICY_HND hSCM, hService;
205         WERROR result = WERR_GENERAL_FAILURE;
206         fstring servicename;
207         SERVICE_STATUS service_status;
208         SERVICE_CONFIG config;
209         fstring ascii_string;
210         
211         if (argc != 1 ) {
212                 d_printf("Usage: net rpc service status <service>\n");
213                 return NT_STATUS_OK;
214         }
215
216         fstrcpy( servicename, argv[0] );
217
218         /* Open the Service Control Manager */
219         
220         result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
221         if ( !W_ERROR_IS_OK(result) ) {
222                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
223                 return werror_to_ntstatus(result);
224         }
225         
226         /* Open the Service */
227         
228         result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, servicename, 
229                 (SC_RIGHT_SVC_QUERY_STATUS|SC_RIGHT_SVC_QUERY_CONFIG) );
230
231         if ( !W_ERROR_IS_OK(result) ) {
232                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
233                 goto done;
234         }
235         
236         /* get the status */
237
238         result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status  );
239         if ( !W_ERROR_IS_OK(result) ) {
240                 d_fprintf(stderr, "Query status request failed.  [%s]\n", dos_errstr(result));
241                 goto done;
242         }
243         
244         d_printf("%s service is %s.\n", servicename, svc_status_string(service_status.state));
245
246         /* get the config */
247
248         result = rpccli_svcctl_query_config(pipe_hnd, mem_ctx, &hService, &config  );
249         if ( !W_ERROR_IS_OK(result) ) {
250                 d_fprintf(stderr, "Query config request failed.  [%s]\n", dos_errstr(result));
251                 goto done;
252         }
253
254         /* print out the configuration information for the service */
255
256         d_printf("Configuration details:\n");
257         d_printf("\tControls Accepted    = 0x%x\n", service_status.controls_accepted);
258         d_printf("\tService Type         = 0x%x\n", config.service_type);
259         d_printf("\tStart Type           = 0x%x\n", config.start_type);
260         d_printf("\tError Control        = 0x%x\n", config.error_control);
261         d_printf("\tTag ID               = 0x%x\n", config.tag_id);
262
263         if ( config.executablepath ) {
264                 rpcstr_pull( ascii_string, config.executablepath->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
265                 d_printf("\tExecutable Path      = %s\n", ascii_string);
266         }
267
268         if ( config.loadordergroup ) {
269                 rpcstr_pull( ascii_string, config.loadordergroup->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
270                 d_printf("\tLoad Order Group     = %s\n", ascii_string);
271         }
272
273         if ( config.dependencies ) {
274                 rpcstr_pull( ascii_string, config.dependencies->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
275                 d_printf("\tDependencies         = %s\n", ascii_string);
276         }
277
278         if ( config.startname ) {
279                 rpcstr_pull( ascii_string, config.startname->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
280                 d_printf("\tStart Name           = %s\n", ascii_string);
281         }
282
283         if ( config.displayname ) {
284                 rpcstr_pull( ascii_string, config.displayname->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
285                 d_printf("\tDisplay Name         = %s\n", ascii_string);
286         }
287
288 done:   
289         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService);
290         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM);
291
292         return werror_to_ntstatus(result);
293 }       
294
295 /********************************************************************
296 ********************************************************************/
297
298 static NTSTATUS rpc_service_stop_internal(const DOM_SID *domain_sid,
299                                         const char *domain_name, 
300                                         struct cli_state *cli,
301                                         struct rpc_pipe_client *pipe_hnd,
302                                         TALLOC_CTX *mem_ctx, 
303                                         int argc,
304                                         const char **argv )
305 {
306         POLICY_HND hSCM;
307         WERROR result = WERR_GENERAL_FAILURE;
308         fstring servicename;
309         
310         if (argc != 1 ) {
311                 d_printf("Usage: net rpc service status <service>\n");
312                 return NT_STATUS_OK;
313         }
314
315         fstrcpy( servicename, argv[0] );
316
317         /* Open the Service Control Manager */
318         
319         result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
320         if ( !W_ERROR_IS_OK(result) ) {
321                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
322                 return werror_to_ntstatus(result);
323         }
324         
325         result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, 
326                 SVCCTL_CONTROL_STOP, SVCCTL_STOPPED );
327                 
328         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM);
329                 
330         return werror_to_ntstatus(result);
331 }       
332
333 /********************************************************************
334 ********************************************************************/
335
336 static NTSTATUS rpc_service_pause_internal(const DOM_SID *domain_sid,
337                                         const char *domain_name, 
338                                         struct cli_state *cli,
339                                         struct rpc_pipe_client *pipe_hnd,
340                                         TALLOC_CTX *mem_ctx, 
341                                         int argc,
342                                         const char **argv )
343 {
344         POLICY_HND hSCM;
345         WERROR result = WERR_GENERAL_FAILURE;
346         fstring servicename;
347         
348         if (argc != 1 ) {
349                 d_printf("Usage: net rpc service status <service>\n");
350                 return NT_STATUS_OK;
351         }
352
353         fstrcpy( servicename, argv[0] );
354
355         /* Open the Service Control Manager */
356         
357         result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
358         if ( !W_ERROR_IS_OK(result) ) {
359                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
360                 return werror_to_ntstatus(result);
361         }
362         
363         result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, 
364                 SVCCTL_CONTROL_PAUSE, SVCCTL_PAUSED );
365                 
366         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM);
367                 
368         return werror_to_ntstatus(result);
369 }       
370
371 /********************************************************************
372 ********************************************************************/
373
374 static NTSTATUS rpc_service_resume_internal(const DOM_SID *domain_sid,
375                                         const char *domain_name, 
376                                         struct cli_state *cli,
377                                         struct rpc_pipe_client *pipe_hnd,
378                                         TALLOC_CTX *mem_ctx, 
379                                         int argc,
380                                         const char **argv )
381 {
382         POLICY_HND hSCM;
383         WERROR result = WERR_GENERAL_FAILURE;
384         fstring servicename;
385         
386         if (argc != 1 ) {
387                 d_printf("Usage: net rpc service status <service>\n");
388                 return NT_STATUS_OK;
389         }
390
391         fstrcpy( servicename, argv[0] );
392
393         /* Open the Service Control Manager */
394         
395         result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
396         if ( !W_ERROR_IS_OK(result) ) {
397                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
398                 return werror_to_ntstatus(result);
399         }
400         
401         result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, 
402                 SVCCTL_CONTROL_CONTINUE, SVCCTL_RUNNING );
403                 
404         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM);
405                 
406         return werror_to_ntstatus(result);
407 }       
408
409 /********************************************************************
410 ********************************************************************/
411
412 static NTSTATUS rpc_service_start_internal(const DOM_SID *domain_sid,
413                                         const char *domain_name, 
414                                         struct cli_state *cli,
415                                         struct rpc_pipe_client *pipe_hnd,
416                                         TALLOC_CTX *mem_ctx, 
417                                         int argc,
418                                         const char **argv )
419 {
420         POLICY_HND hSCM, hService;
421         WERROR result = WERR_GENERAL_FAILURE;
422         fstring servicename;
423         uint32 state = 0;
424         
425         if (argc != 1 ) {
426                 d_printf("Usage: net rpc service status <service>\n");
427                 return NT_STATUS_OK;
428         }
429
430         fstrcpy( servicename, argv[0] );
431
432         /* Open the Service Control Manager */
433         
434         result = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
435         if ( !W_ERROR_IS_OK(result) ) {
436                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
437                 return werror_to_ntstatus(result);
438         }
439         
440         /* Open the Service */
441         
442         result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, 
443                 servicename, SC_RIGHT_SVC_START );
444
445         if ( !W_ERROR_IS_OK(result) ) {
446                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
447                 goto done;
448         }
449         
450         /* get the status */
451
452         result = rpccli_svcctl_start_service(pipe_hnd, mem_ctx, &hService, NULL, 0 );
453         if ( !W_ERROR_IS_OK(result) ) {
454                 d_fprintf(stderr, "Query status request failed.  [%s]\n", dos_errstr(result));
455                 goto done;
456         }
457         
458         result = watch_service_state(pipe_hnd, mem_ctx, &hSCM, servicename, SVCCTL_RUNNING, &state  );
459         
460         if ( W_ERROR_IS_OK(result) && (state == SVCCTL_RUNNING) )
461                 d_printf("Successfully started service: %s\n", servicename );
462         else
463                 d_fprintf(stderr, "Failed to start service: %s [%s]\n", servicename, dos_errstr(result) );
464         
465 done:   
466         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService);
467         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM);
468
469         return werror_to_ntstatus(result);
470 }
471
472 /********************************************************************
473 ********************************************************************/
474
475 static int rpc_service_list( int argc, const char **argv )
476 {
477         return run_rpc_command( NULL, PI_SVCCTL, 0, 
478                 rpc_service_list_internal, argc, argv );
479 }
480
481 /********************************************************************
482 ********************************************************************/
483
484 static int rpc_service_start( int argc, const char **argv )
485 {
486         return run_rpc_command( NULL, PI_SVCCTL, 0, 
487                 rpc_service_start_internal, argc, argv );
488 }
489
490 /********************************************************************
491 ********************************************************************/
492
493 static int rpc_service_stop( int argc, const char **argv )
494 {
495         return run_rpc_command( NULL, PI_SVCCTL, 0, 
496                 rpc_service_stop_internal, argc, argv );
497 }
498
499 /********************************************************************
500 ********************************************************************/
501
502 static int rpc_service_resume( int argc, const char **argv )
503 {
504         return run_rpc_command( NULL, PI_SVCCTL, 0, 
505                 rpc_service_resume_internal, argc, argv );
506 }
507
508 /********************************************************************
509 ********************************************************************/
510
511 static int rpc_service_pause( int argc, const char **argv )
512 {
513         return run_rpc_command( NULL, PI_SVCCTL, 0, 
514                 rpc_service_pause_internal, argc, argv );
515 }
516
517 /********************************************************************
518 ********************************************************************/
519
520 static int rpc_service_status( int argc, const char **argv )
521 {
522         return run_rpc_command( NULL, PI_SVCCTL, 0, 
523                 rpc_service_status_internal, argc, argv );
524 }
525
526 /********************************************************************
527 ********************************************************************/
528
529 static int net_help_service( int argc, const char **argv )
530 {
531         d_printf("net rpc service list               View configured Win32 services\n");
532         d_printf("net rpc service start <service>    Start a service\n");
533         d_printf("net rpc service stop <service>     Stop a service\n");
534         d_printf("net rpc service pause <service>    Pause a service\n");
535         d_printf("net rpc service resume <service>   Resume a paused service\n");
536         d_printf("net rpc service status <service>   View the current status of a service\n");
537         
538         return -1;
539 }
540
541 /********************************************************************
542 ********************************************************************/
543
544 int net_rpc_service(int argc, const char **argv) 
545 {
546         struct functable func[] = {
547                 {"list", rpc_service_list},
548                 {"start", rpc_service_start},
549                 {"stop", rpc_service_stop},
550                 {"pause", rpc_service_pause},
551                 {"resume", rpc_service_resume},
552                 {"status", rpc_service_status},
553                 {NULL, NULL}
554         };
555         
556         if ( argc )
557                 return net_run_function( argc, argv, func, net_help_service );
558                 
559         return net_help_service( argc, argv );
560 }