87434f482fccac1deb275349b1a5deb7a48f1fde
[jra/samba/.git] / source3 / rpc_client / cli_svcctl.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Gerald 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
21
22 #include "includes.h"
23 #include "rpc_client.h"
24
25 struct svc_state_msg {
26         uint32 flag;
27         const char *message;
28 };
29
30 static struct svc_state_msg state_msg_table[] = {
31         { SVCCTL_STOPPED,            "stopped" },
32         { SVCCTL_START_PENDING,      "start pending" },
33         { SVCCTL_STOP_PENDING,       "stop pending" },
34         { SVCCTL_RUNNING,            "running" },
35         { SVCCTL_CONTINUE_PENDING,   "resume pending" },
36         { SVCCTL_PAUSE_PENDING,      "pause pending" },
37         { SVCCTL_PAUSED,             "paused" },
38         { 0,                          NULL }
39 };
40         
41
42 /********************************************************************
43 ********************************************************************/
44 const char* svc_status_string( uint32 state )
45 {
46         static fstring msg;
47         int i;
48         
49         fstr_sprintf( msg, "Unknown State [%d]", state );
50         
51         for ( i=0; state_msg_table[i].message; i++ ) {
52                 if ( state_msg_table[i].flag == state ) {
53                         fstrcpy( msg, state_msg_table[i].message );
54                         break;  
55                 }
56         }
57         
58         return msg;
59 }
60
61 /********************************************************************
62 ********************************************************************/
63
64 WERROR rpccli_svcctl_open_scm(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
65                               POLICY_HND *hSCM, uint32 access_desired )
66 {
67         SVCCTL_Q_OPEN_SCMANAGER in;
68         SVCCTL_R_OPEN_SCMANAGER out;
69         prs_struct qbuf, rbuf;
70         fstring server;
71         
72         ZERO_STRUCT(in);
73         ZERO_STRUCT(out);
74         
75         /* leave the database name NULL to get the default service db */
76
77         in.database = NULL;
78
79         /* set the server name */
80
81         if ( !(in.servername = TALLOC_P( mem_ctx, UNISTR2 )) )
82                 return WERR_NOMEM;
83         fstr_sprintf( server, "\\\\%s", cli->cli->desthost );
84         init_unistr2( in.servername, server, UNI_STR_TERMINATE );
85
86         in.access = access_desired;
87         
88         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SCMANAGER_W, 
89                     in, out, 
90                     qbuf, rbuf,
91                     svcctl_io_q_open_scmanager,
92                     svcctl_io_r_open_scmanager, 
93                     WERR_GENERAL_FAILURE );
94         
95         if ( !W_ERROR_IS_OK( out.status ) )
96                 return out.status;
97
98         memcpy( hSCM, &out.handle, sizeof(POLICY_HND) );
99         
100         return out.status;
101 }
102
103 /********************************************************************
104 ********************************************************************/
105
106 WERROR rpccli_svcctl_open_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
107                                 POLICY_HND *hSCM, POLICY_HND *hService, 
108                                 const char *servicename, uint32 access_desired )
109 {
110         SVCCTL_Q_OPEN_SERVICE in;
111         SVCCTL_R_OPEN_SERVICE out;
112         prs_struct qbuf, rbuf;
113         
114         ZERO_STRUCT(in);
115         ZERO_STRUCT(out);
116         
117         memcpy( &in.handle, hSCM, sizeof(POLICY_HND) );
118         init_unistr2( &in.servicename, servicename, UNI_STR_TERMINATE );
119         in.access = access_desired;
120         
121         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, 
122                     in, out, 
123                     qbuf, rbuf,
124                     svcctl_io_q_open_service,
125                     svcctl_io_r_open_service, 
126                     WERR_GENERAL_FAILURE );
127         
128         if ( !W_ERROR_IS_OK( out.status ) )
129                 return out.status;
130
131         memcpy( hService, &out.handle, sizeof(POLICY_HND) );
132         
133         return out.status;
134 }
135
136 /*******************************************************************
137 *******************************************************************/
138
139 WERROR rpccli_svcctl_enumerate_services( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
140                                       POLICY_HND *hSCM, uint32 type, uint32 state, 
141                                       uint32 *returned, ENUM_SERVICES_STATUS **service_array  )
142 {
143         SVCCTL_Q_ENUM_SERVICES_STATUS in;
144         SVCCTL_R_ENUM_SERVICES_STATUS out;
145         prs_struct qbuf, rbuf;
146         uint32 resume = 0;
147         ENUM_SERVICES_STATUS *services;
148         int i;
149
150         ZERO_STRUCT(in);
151         ZERO_STRUCT(out);
152         
153         /* setup the request */
154         
155         memcpy( &in.handle, hSCM, sizeof(POLICY_HND) );
156         
157         in.type        = type;
158         in.state       = state;
159         in.resume      = &resume;
160         
161         /* first time is to get the buffer size */
162         in.buffer_size = 0;
163
164         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
165                     in, out, 
166                     qbuf, rbuf,
167                     svcctl_io_q_enum_services_status,
168                     svcctl_io_r_enum_services_status, 
169                     WERR_GENERAL_FAILURE );
170
171         /* second time with correct buffer size...should be ok */
172         
173         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
174                 in.buffer_size = out.needed;
175
176                 CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
177                             in, out, 
178                             qbuf, rbuf,
179                             svcctl_io_q_enum_services_status,
180                             svcctl_io_r_enum_services_status, 
181                             WERR_GENERAL_FAILURE );
182         }
183         
184         if ( !W_ERROR_IS_OK(out.status) ) 
185                 return out.status;
186                 
187         /* pull out the data */
188         if (out.returned) {
189                 if ( !(services = TALLOC_ARRAY( mem_ctx, ENUM_SERVICES_STATUS, out.returned )) ) 
190                         return WERR_NOMEM;
191         } else {
192                 services = NULL;
193         }
194                 
195         for ( i=0; i<out.returned; i++ ) {
196                 svcctl_io_enum_services_status( "", &services[i], &out.buffer, 0 );
197         }
198         
199         *service_array = services;
200         *returned      = out.returned;
201         
202         return out.status;
203 }
204
205 /*******************************************************************
206 *******************************************************************/
207
208 WERROR rpccli_svcctl_query_status( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
209                                 POLICY_HND *hService, SERVICE_STATUS *status )
210 {
211         SVCCTL_Q_QUERY_STATUS in;
212         SVCCTL_R_QUERY_STATUS out;
213         prs_struct qbuf, rbuf;
214         
215         ZERO_STRUCT(in);
216         ZERO_STRUCT(out);
217         
218         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
219         
220         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, 
221                     in, out, 
222                     qbuf, rbuf,
223                     svcctl_io_q_query_status,
224                     svcctl_io_r_query_status, 
225                     WERR_GENERAL_FAILURE );
226         
227         if ( !W_ERROR_IS_OK( out.status ) )
228                 return out.status;
229
230         memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) );
231         
232         return out.status;
233 }
234
235 /*******************************************************************
236 *******************************************************************/
237
238 WERROR rpccli_svcctl_query_config(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
239                                 POLICY_HND *hService, SERVICE_CONFIG *config )
240 {
241         SVCCTL_Q_QUERY_SERVICE_CONFIG in;
242         SVCCTL_R_QUERY_SERVICE_CONFIG out;
243         prs_struct qbuf, rbuf;
244         
245         ZERO_STRUCT(in);
246         ZERO_STRUCT(out);
247         
248         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
249         in.buffer_size = 0;
250         
251         
252         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, 
253                     in, out, 
254                     qbuf, rbuf,
255                     svcctl_io_q_query_service_config,
256                     svcctl_io_r_query_service_config, 
257                     WERR_GENERAL_FAILURE );
258         
259         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
260                 in.buffer_size = out.needed;
261
262                 CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W,
263                             in, out, 
264                             qbuf, rbuf,
265                             svcctl_io_q_query_service_config,
266                             svcctl_io_r_query_service_config, 
267                             WERR_GENERAL_FAILURE );
268         }
269         
270         if ( !W_ERROR_IS_OK( out.status ) )
271                 return out.status;
272
273         memcpy( config, &out.config, sizeof(SERVICE_CONFIG) );
274         
275         config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
276         config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
277         config->dependencies   = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
278         config->startname      = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
279         config->displayname    = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
280         
281         if ( out.config.executablepath ) {
282                 config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
283                 copy_unistr2( config->executablepath, out.config.executablepath );
284         }
285
286         if ( out.config.loadordergroup ) {
287                 config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
288                 copy_unistr2( config->loadordergroup, out.config.loadordergroup );
289         }
290
291         if ( out.config.dependencies ) {
292                 config->dependencies = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
293                 copy_unistr2( config->dependencies, out.config.dependencies );
294         }
295
296         if ( out.config.startname ) {
297                 config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
298                 copy_unistr2( config->startname, out.config.startname );
299         }
300
301         if ( out.config.displayname ) {
302                 config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
303                 copy_unistr2( config->displayname, out.config.displayname );
304         }
305         
306         return out.status;
307 }
308
309 /*******************************************************************
310 *******************************************************************/
311
312 WERROR rpccli_svcctl_start_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
313                                  POLICY_HND *hService,
314                                  const char **parm_array, uint32 parmcount )
315 {
316         SVCCTL_Q_START_SERVICE in;
317         SVCCTL_R_START_SERVICE out;
318         prs_struct qbuf, rbuf;
319         
320         ZERO_STRUCT(in);
321         ZERO_STRUCT(out);
322         
323         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
324         
325         in.parmcount  = 0;
326         in.parameters = NULL;
327         
328         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W,
329                     in, out, 
330                     qbuf, rbuf,
331                     svcctl_io_q_start_service,
332                     svcctl_io_r_start_service,
333                     WERR_GENERAL_FAILURE );
334         
335         return out.status;
336 }
337
338 /*******************************************************************
339 *******************************************************************/
340
341 WERROR rpccli_svcctl_control_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
342                                    POLICY_HND *hService, uint32 control,
343                                    SERVICE_STATUS *status )
344 {
345         SVCCTL_Q_CONTROL_SERVICE in;
346         SVCCTL_R_CONTROL_SERVICE out;
347         prs_struct qbuf, rbuf;
348         
349         ZERO_STRUCT(in);
350         ZERO_STRUCT(out);
351         
352         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
353         in.control = control;
354         
355         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, 
356                     in, out, 
357                     qbuf, rbuf,
358                     svcctl_io_q_control_service,
359                     svcctl_io_r_control_service,
360                     WERR_GENERAL_FAILURE );
361         
362         if ( !W_ERROR_IS_OK( out.status ) )
363                 return out.status;
364
365         memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) );
366         
367         return out.status;
368 }
369
370
371 /*******************************************************************
372 *******************************************************************/
373
374 WERROR rpccli_svcctl_get_dispname( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
375                                 POLICY_HND *hService, fstring displayname )
376 {
377         SVCCTL_Q_GET_DISPLAY_NAME in;
378         SVCCTL_R_GET_DISPLAY_NAME out;
379         prs_struct qbuf, rbuf;
380         
381         ZERO_STRUCT(in);
382         ZERO_STRUCT(out);
383         
384         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
385         in.display_name_len = 0;
386         
387         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
388                     in, out, 
389                     qbuf, rbuf,
390                     svcctl_io_q_get_display_name,
391                     svcctl_io_r_get_display_name, 
392                     WERR_GENERAL_FAILURE );
393         
394         /* second time with correct buffer size...should be ok */
395         
396         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
397                 in.display_name_len = out.display_name_len;
398
399                 CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
400                             in, out, 
401                             qbuf, rbuf,
402                             svcctl_io_q_get_display_name,
403                             svcctl_io_r_get_display_name, 
404                             WERR_GENERAL_FAILURE );
405         }
406
407         if ( !W_ERROR_IS_OK( out.status ) )
408                 return out.status;
409
410         rpcstr_pull( displayname, out.displayname.buffer, sizeof(displayname), -1, STR_TERMINATE );
411         
412         return out.status;
413 }