Use rpccli_svcctl_ControlService() in net.
[kai/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, see <http://www.gnu.org/licenses/>.  */
18
19 #include "includes.h"
20 #include "utils/net.h"
21
22
23 #define CLI_SERVER_NAME_SLASH(_ctx, _p, _cli) \
24         _p = talloc_asprintf(_ctx, "\\\\%s", _cli->cli->desthost);
25
26 /********************************************************************
27 ********************************************************************/
28
29 static WERROR query_service_state(struct rpc_pipe_client *pipe_hnd,
30                                 TALLOC_CTX *mem_ctx,
31                                 POLICY_HND *hSCM,
32                                 const char *service,
33                                 uint32 *state )
34 {
35         POLICY_HND hService;
36         SERVICE_STATUS service_status;
37         WERROR result = WERR_GENERAL_FAILURE;
38         NTSTATUS status;
39
40         /* now cycle until the status is actually 'watch_state' */
41
42         status = rpccli_svcctl_OpenServiceW(pipe_hnd, mem_ctx,
43                                             hSCM,
44                                             service,
45                                             SC_RIGHT_SVC_QUERY_STATUS,
46                                             &hService,
47                                             &result);
48         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
49                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
50                 return result;
51         }
52
53         result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status  );
54         if ( W_ERROR_IS_OK(result) ) {
55                 *state = service_status.state;
56         }
57
58         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL);
59
60         return result;
61 }
62
63 /********************************************************************
64 ********************************************************************/
65
66 static WERROR watch_service_state(struct rpc_pipe_client *pipe_hnd,
67                                 TALLOC_CTX *mem_ctx,
68                                 POLICY_HND *hSCM,
69                                 const char *service,
70                                 uint32 watch_state,
71                                 uint32 *final_state )
72 {
73         uint32 i;
74         uint32 state = 0;
75         WERROR result = WERR_GENERAL_FAILURE;
76
77
78         i = 0;
79         while ( (state != watch_state ) && i<30 ) {
80                 /* get the status */
81
82                 result = query_service_state(pipe_hnd, mem_ctx, hSCM, service, &state  );
83                 if ( !W_ERROR_IS_OK(result) ) {
84                         break;
85                 }
86
87                 d_printf(".");
88                 i++;
89                 sys_usleep( 100 );
90         }
91         d_printf("\n");
92
93         *final_state = state;
94
95         return result;
96 }
97
98 /********************************************************************
99 ********************************************************************/
100
101 static WERROR control_service(struct rpc_pipe_client *pipe_hnd,
102                                 TALLOC_CTX *mem_ctx,
103                                 POLICY_HND *hSCM,
104                                 const char *service,
105                                 uint32 control,
106                                 uint32 watch_state )
107 {
108         POLICY_HND hService;
109         WERROR result = WERR_GENERAL_FAILURE;
110         NTSTATUS status;
111         SERVICE_STATUS service_status;
112         uint32 state = 0;
113
114         /* Open the Service */
115
116         status = rpccli_svcctl_OpenServiceW(pipe_hnd, mem_ctx,
117                                             hSCM,
118                                             service,
119                                             (SC_RIGHT_SVC_STOP|SC_RIGHT_SVC_PAUSE_CONTINUE),
120                                             &hService,
121                                             &result);
122
123         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
124                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
125                 goto done;
126         }
127
128         /* get the status */
129
130         status = rpccli_svcctl_ControlService(pipe_hnd, mem_ctx,
131                                               &hService,
132                                               control,
133                                               &service_status,
134                                               &result);
135
136         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
137                 d_fprintf(stderr, "Control service request failed.  [%s]\n", dos_errstr(result));
138                 goto done;
139         }
140
141         /* loop -- checking the state until we are where we want to be */
142
143         result = watch_service_state(pipe_hnd, mem_ctx, hSCM, service, watch_state, &state );
144
145         d_printf("%s service is %s.\n", service, svc_status_string(state));
146
147 done:
148         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL);
149
150         return result;
151 }
152
153 /********************************************************************
154 ********************************************************************/
155
156 static NTSTATUS rpc_service_list_internal(const DOM_SID *domain_sid,
157                                         const char *domain_name,
158                                         struct cli_state *cli,
159                                         struct rpc_pipe_client *pipe_hnd,
160                                         TALLOC_CTX *mem_ctx,
161                                         int argc,
162                                         const char **argv )
163 {
164         POLICY_HND hSCM;
165         ENUM_SERVICES_STATUS *services;
166         WERROR result = WERR_GENERAL_FAILURE;
167         NTSTATUS status;
168         fstring servicename;
169         fstring displayname;
170         uint32 num_services = 0;
171         const char *server_name;
172         int i;
173
174         if (argc != 0 ) {
175                 d_printf("Usage: net rpc service list\n");
176                 return NT_STATUS_OK;
177         }
178
179         CLI_SERVER_NAME_SLASH(mem_ctx, server_name, pipe_hnd);
180         NT_STATUS_HAVE_NO_MEMORY(server_name);
181
182         status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
183                                               server_name,
184                                               NULL,
185                                               SC_RIGHT_MGR_ENUMERATE_SERVICE,
186                                               &hSCM,
187                                               &result);
188         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
189                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
190                 return werror_to_ntstatus(result);
191         }
192
193         result = rpccli_svcctl_enumerate_services(pipe_hnd, mem_ctx, &hSCM, SVCCTL_TYPE_WIN32,
194                 SVCCTL_STATE_ALL, &num_services, &services );
195
196         if ( !W_ERROR_IS_OK(result) ) {
197                 d_fprintf(stderr, "Failed to enumerate services.  [%s]\n", dos_errstr(result));
198                 goto done;
199         }
200
201         if ( num_services == 0 )
202                 d_printf("No services returned\n");
203
204         for ( i=0; i<num_services; i++ ) {
205                 rpcstr_pull( servicename, services[i].servicename.buffer, sizeof(servicename), -1, STR_TERMINATE );
206                 rpcstr_pull( displayname, services[i].displayname.buffer, sizeof(displayname), -1, STR_TERMINATE );
207
208                 d_printf("%-20s    \"%s\"\n", servicename, displayname);
209         }
210
211 done:
212         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
213
214         return werror_to_ntstatus(result);
215 }
216
217 /********************************************************************
218 ********************************************************************/
219
220 static NTSTATUS rpc_service_status_internal(const DOM_SID *domain_sid,
221                                                 const char *domain_name,
222                                                 struct cli_state *cli,
223                                                 struct rpc_pipe_client *pipe_hnd,
224                                                 TALLOC_CTX *mem_ctx,
225                                                 int argc,
226                                                 const char **argv )
227 {
228         POLICY_HND hSCM, hService;
229         WERROR result = WERR_GENERAL_FAILURE;
230         NTSTATUS status;
231         SERVICE_STATUS service_status;
232         SERVICE_CONFIG config;
233         fstring ascii_string;
234         const char *server_name;
235
236         if (argc != 1 ) {
237                 d_printf("Usage: net rpc service status <service>\n");
238                 return NT_STATUS_OK;
239         }
240
241         /* Open the Service Control Manager */
242         CLI_SERVER_NAME_SLASH(mem_ctx, server_name, pipe_hnd);
243         NT_STATUS_HAVE_NO_MEMORY(server_name);
244
245         status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
246                                               server_name,
247                                               NULL,
248                                               SC_RIGHT_MGR_ENUMERATE_SERVICE,
249                                               &hSCM,
250                                               &result);
251         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
252                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
253                 return werror_to_ntstatus(result);
254         }
255
256         /* Open the Service */
257
258         status = rpccli_svcctl_OpenServiceW(pipe_hnd, mem_ctx,
259                                             &hSCM,
260                                             argv[0],
261                                             (SC_RIGHT_SVC_QUERY_STATUS|SC_RIGHT_SVC_QUERY_CONFIG),
262                                             &hService,
263                                             &result);
264
265         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
266                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
267                 goto done;
268         }
269
270         /* get the status */
271
272         result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status  );
273         if ( !W_ERROR_IS_OK(result) ) {
274                 d_fprintf(stderr, "Query status request failed.  [%s]\n", dos_errstr(result));
275                 goto done;
276         }
277
278         d_printf("%s service is %s.\n", argv[0], svc_status_string(service_status.state));
279
280         /* get the config */
281
282         result = rpccli_svcctl_query_config(pipe_hnd, mem_ctx, &hService, &config  );
283         if ( !W_ERROR_IS_OK(result) ) {
284                 d_fprintf(stderr, "Query config request failed.  [%s]\n", dos_errstr(result));
285                 goto done;
286         }
287
288         /* print out the configuration information for the service */
289
290         d_printf("Configuration details:\n");
291         d_printf("\tControls Accepted    = 0x%x\n", service_status.controls_accepted);
292         d_printf("\tService Type         = 0x%x\n", config.service_type);
293         d_printf("\tStart Type           = 0x%x\n", config.start_type);
294         d_printf("\tError Control        = 0x%x\n", config.error_control);
295         d_printf("\tTag ID               = 0x%x\n", config.tag_id);
296
297         if ( config.executablepath ) {
298                 rpcstr_pull( ascii_string, config.executablepath->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
299                 d_printf("\tExecutable Path      = %s\n", ascii_string);
300         }
301
302         if ( config.loadordergroup ) {
303                 rpcstr_pull( ascii_string, config.loadordergroup->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
304                 d_printf("\tLoad Order Group     = %s\n", ascii_string);
305         }
306
307         if ( config.dependencies ) {
308                 rpcstr_pull( ascii_string, config.dependencies->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
309                 d_printf("\tDependencies         = %s\n", ascii_string);
310         }
311
312         if ( config.startname ) {
313                 rpcstr_pull( ascii_string, config.startname->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
314                 d_printf("\tStart Name           = %s\n", ascii_string);
315         }
316
317         if ( config.displayname ) {
318                 rpcstr_pull( ascii_string, config.displayname->buffer, sizeof(ascii_string), -1, STR_TERMINATE );
319                 d_printf("\tDisplay Name         = %s\n", ascii_string);
320         }
321
322 done:
323         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL);
324         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
325
326         return werror_to_ntstatus(result);
327 }
328
329 /********************************************************************
330 ********************************************************************/
331
332 static NTSTATUS rpc_service_stop_internal(const DOM_SID *domain_sid,
333                                         const char *domain_name,
334                                         struct cli_state *cli,
335                                         struct rpc_pipe_client *pipe_hnd,
336                                         TALLOC_CTX *mem_ctx,
337                                         int argc,
338                                         const char **argv )
339 {
340         POLICY_HND hSCM;
341         WERROR result = WERR_GENERAL_FAILURE;
342         NTSTATUS status;
343         fstring servicename;
344         const char *server_name;
345
346         if (argc != 1 ) {
347                 d_printf("Usage: net rpc service status <service>\n");
348                 return NT_STATUS_OK;
349         }
350
351         fstrcpy( servicename, argv[0] );
352
353         /* Open the Service Control Manager */
354         CLI_SERVER_NAME_SLASH(mem_ctx, server_name, pipe_hnd);
355         NT_STATUS_HAVE_NO_MEMORY(server_name);
356
357         status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
358                                               server_name,
359                                               NULL,
360                                               SC_RIGHT_MGR_ENUMERATE_SERVICE,
361                                               &hSCM,
362                                               &result);
363         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
364                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
365                 return werror_to_ntstatus(result);
366         }
367
368         result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename,
369                 SVCCTL_CONTROL_STOP, SVCCTL_STOPPED );
370
371         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
372
373         return werror_to_ntstatus(result);
374 }
375
376 /********************************************************************
377 ********************************************************************/
378
379 static NTSTATUS rpc_service_pause_internal(const DOM_SID *domain_sid,
380                                         const char *domain_name,
381                                         struct cli_state *cli,
382                                         struct rpc_pipe_client *pipe_hnd,
383                                         TALLOC_CTX *mem_ctx,
384                                         int argc,
385                                         const char **argv )
386 {
387         POLICY_HND hSCM;
388         WERROR result = WERR_GENERAL_FAILURE;
389         NTSTATUS status;
390         fstring servicename;
391         const char *server_name;
392
393         if (argc != 1 ) {
394                 d_printf("Usage: net rpc service status <service>\n");
395                 return NT_STATUS_OK;
396         }
397
398         fstrcpy( servicename, argv[0] );
399
400         /* Open the Service Control Manager */
401         CLI_SERVER_NAME_SLASH(mem_ctx, server_name, pipe_hnd);
402         NT_STATUS_HAVE_NO_MEMORY(server_name);
403
404         status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
405                                               server_name,
406                                               NULL,
407                                               SC_RIGHT_MGR_ENUMERATE_SERVICE,
408                                               &hSCM,
409                                               &result);
410         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
411                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
412                 return werror_to_ntstatus(result);
413         }
414
415         result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename,
416                 SVCCTL_CONTROL_PAUSE, SVCCTL_PAUSED );
417
418         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
419
420         return werror_to_ntstatus(result);
421 }
422
423 /********************************************************************
424 ********************************************************************/
425
426 static NTSTATUS rpc_service_resume_internal(const DOM_SID *domain_sid,
427                                         const char *domain_name,
428                                         struct cli_state *cli,
429                                         struct rpc_pipe_client *pipe_hnd,
430                                         TALLOC_CTX *mem_ctx,
431                                         int argc,
432                                         const char **argv )
433 {
434         POLICY_HND hSCM;
435         WERROR result = WERR_GENERAL_FAILURE;
436         NTSTATUS status;
437         fstring servicename;
438         const char *server_name;
439
440         if (argc != 1 ) {
441                 d_printf("Usage: net rpc service status <service>\n");
442                 return NT_STATUS_OK;
443         }
444
445         fstrcpy( servicename, argv[0] );
446
447         /* Open the Service Control Manager */
448         CLI_SERVER_NAME_SLASH(mem_ctx, server_name, pipe_hnd);
449         NT_STATUS_HAVE_NO_MEMORY(server_name);
450
451         status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
452                                               server_name,
453                                               NULL,
454                                               SC_RIGHT_MGR_ENUMERATE_SERVICE,
455                                               &hSCM,
456                                               &result);
457         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
458                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
459                 return werror_to_ntstatus(result);
460         }
461
462         result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename,
463                 SVCCTL_CONTROL_CONTINUE, SVCCTL_RUNNING );
464
465         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
466
467         return werror_to_ntstatus(result);
468 }
469
470 /********************************************************************
471 ********************************************************************/
472
473 static NTSTATUS rpc_service_start_internal(const DOM_SID *domain_sid,
474                                         const char *domain_name,
475                                         struct cli_state *cli,
476                                         struct rpc_pipe_client *pipe_hnd,
477                                         TALLOC_CTX *mem_ctx,
478                                         int argc,
479                                         const char **argv )
480 {
481         POLICY_HND hSCM, hService;
482         WERROR result = WERR_GENERAL_FAILURE;
483         NTSTATUS status;
484         uint32 state = 0;
485         const char *server_name;
486
487         if (argc != 1 ) {
488                 d_printf("Usage: net rpc service status <service>\n");
489                 return NT_STATUS_OK;
490         }
491
492         /* Open the Service Control Manager */
493         CLI_SERVER_NAME_SLASH(mem_ctx, server_name, pipe_hnd);
494         NT_STATUS_HAVE_NO_MEMORY(server_name);
495
496         status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
497                                               server_name,
498                                               NULL,
499                                               SC_RIGHT_MGR_ENUMERATE_SERVICE,
500                                               &hSCM,
501                                               &result);
502         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
503                 d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
504                 return werror_to_ntstatus(result);
505         }
506
507         /* Open the Service */
508
509         status = rpccli_svcctl_OpenServiceW(pipe_hnd, mem_ctx,
510                                             &hSCM,
511                                             argv[0],
512                                             SC_RIGHT_SVC_START,
513                                             &hService,
514                                             &result);
515
516         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
517                 d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
518                 goto done;
519         }
520
521         /* get the status */
522
523         status = rpccli_svcctl_StartServiceW(pipe_hnd, mem_ctx,
524                                              &hService,
525                                              0,
526                                              NULL,
527                                              &result);
528
529         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result) ) {
530                 d_fprintf(stderr, "Query status request failed.  [%s]\n", dos_errstr(result));
531                 goto done;
532         }
533
534         result = watch_service_state(pipe_hnd, mem_ctx, &hSCM, argv[0], SVCCTL_RUNNING, &state  );
535
536         if ( W_ERROR_IS_OK(result) && (state == SVCCTL_RUNNING) )
537                 d_printf("Successfully started service: %s\n", argv[0] );
538         else
539                 d_fprintf(stderr, "Failed to start service: %s [%s]\n", argv[0], dos_errstr(result) );
540
541 done:
542         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hService, NULL);
543         rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);
544
545         return werror_to_ntstatus(result);
546 }
547
548 /********************************************************************
549 ********************************************************************/
550
551 static int rpc_service_list( int argc, const char **argv )
552 {
553         return run_rpc_command( NULL, PI_SVCCTL, 0,
554                 rpc_service_list_internal, argc, argv );
555 }
556
557 /********************************************************************
558 ********************************************************************/
559
560 static int rpc_service_start( int argc, const char **argv )
561 {
562         return run_rpc_command( NULL, PI_SVCCTL, 0,
563                 rpc_service_start_internal, argc, argv );
564 }
565
566 /********************************************************************
567 ********************************************************************/
568
569 static int rpc_service_stop( int argc, const char **argv )
570 {
571         return run_rpc_command( NULL, PI_SVCCTL, 0,
572                 rpc_service_stop_internal, argc, argv );
573 }
574
575 /********************************************************************
576 ********************************************************************/
577
578 static int rpc_service_resume( int argc, const char **argv )
579 {
580         return run_rpc_command( NULL, PI_SVCCTL, 0,
581                 rpc_service_resume_internal, argc, argv );
582 }
583
584 /********************************************************************
585 ********************************************************************/
586
587 static int rpc_service_pause( int argc, const char **argv )
588 {
589         return run_rpc_command( NULL, PI_SVCCTL, 0,
590                 rpc_service_pause_internal, argc, argv );
591 }
592
593 /********************************************************************
594 ********************************************************************/
595
596 static int rpc_service_status( int argc, const char **argv )
597 {
598         return run_rpc_command( NULL, PI_SVCCTL, 0,
599                 rpc_service_status_internal, argc, argv );
600 }
601
602 /********************************************************************
603 ********************************************************************/
604
605 static int net_help_service( int argc, const char **argv )
606 {
607         d_printf("net rpc service list               View configured Win32 services\n");
608         d_printf("net rpc service start <service>    Start a service\n");
609         d_printf("net rpc service stop <service>     Stop a service\n");
610         d_printf("net rpc service pause <service>    Pause a service\n");
611         d_printf("net rpc service resume <service>   Resume a paused service\n");
612         d_printf("net rpc service status <service>   View the current status of a service\n");
613
614         return -1;
615 }
616
617 /********************************************************************
618 ********************************************************************/
619
620 int net_rpc_service(int argc, const char **argv)
621 {
622         struct functable func[] = {
623                 {"list", rpc_service_list},
624                 {"start", rpc_service_start},
625                 {"stop", rpc_service_stop},
626                 {"pause", rpc_service_pause},
627                 {"resume", rpc_service_resume},
628                 {"status", rpc_service_status},
629                 {NULL, NULL}
630         };
631
632         if ( argc )
633                 return net_run_function( argc, argv, func, net_help_service );
634
635         return net_help_service( argc, argv );
636 }