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