Initial import
[samba] / source / 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 2 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_close_service(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService )
140 {
141         SVCCTL_Q_CLOSE_SERVICE in;
142         SVCCTL_R_CLOSE_SERVICE out;
143         prs_struct qbuf, rbuf;
144         
145         ZERO_STRUCT(in);
146         ZERO_STRUCT(out);
147         
148         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
149         
150         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CLOSE_SERVICE, 
151                     in, out, 
152                     qbuf, rbuf,
153                     svcctl_io_q_close_service,
154                     svcctl_io_r_close_service, 
155                     WERR_GENERAL_FAILURE );
156
157         return out.status;
158 }
159
160 /*******************************************************************
161 *******************************************************************/
162
163 WERROR rpccli_svcctl_enumerate_services( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
164                                       POLICY_HND *hSCM, uint32 type, uint32 state, 
165                                       uint32 *returned, ENUM_SERVICES_STATUS **service_array  )
166 {
167         SVCCTL_Q_ENUM_SERVICES_STATUS in;
168         SVCCTL_R_ENUM_SERVICES_STATUS out;
169         prs_struct qbuf, rbuf;
170         uint32 resume = 0;
171         ENUM_SERVICES_STATUS *services;
172         int i;
173
174         ZERO_STRUCT(in);
175         ZERO_STRUCT(out);
176         
177         /* setup the request */
178         
179         memcpy( &in.handle, hSCM, sizeof(POLICY_HND) );
180         
181         in.type        = type;
182         in.state       = state;
183         in.resume      = &resume;
184         
185         /* first time is to get the buffer size */
186         in.buffer_size = 0;
187
188         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
189                     in, out, 
190                     qbuf, rbuf,
191                     svcctl_io_q_enum_services_status,
192                     svcctl_io_r_enum_services_status, 
193                     WERR_GENERAL_FAILURE );
194
195         /* second time with correct buffer size...should be ok */
196         
197         if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
198                 in.buffer_size = out.needed;
199
200                 CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
201                             in, out, 
202                             qbuf, rbuf,
203                             svcctl_io_q_enum_services_status,
204                             svcctl_io_r_enum_services_status, 
205                             WERR_GENERAL_FAILURE );
206         }
207         
208         if ( !W_ERROR_IS_OK(out.status) ) 
209                 return out.status;
210                 
211         /* pull out the data */
212         if ( !(services = TALLOC_ARRAY( mem_ctx, ENUM_SERVICES_STATUS, out.returned )) ) 
213                 return WERR_NOMEM;
214                 
215         for ( i=0; i<out.returned; i++ ) {
216                 svcctl_io_enum_services_status( "", &services[i], &out.buffer, 0 );
217         }
218         
219         *service_array = services;
220         *returned      = out.returned;
221         
222         return out.status;
223 }
224
225 /*******************************************************************
226 *******************************************************************/
227
228 WERROR rpccli_svcctl_query_status( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
229                                 POLICY_HND *hService, SERVICE_STATUS *status )
230 {
231         SVCCTL_Q_QUERY_STATUS in;
232         SVCCTL_R_QUERY_STATUS out;
233         prs_struct qbuf, rbuf;
234         
235         ZERO_STRUCT(in);
236         ZERO_STRUCT(out);
237         
238         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
239         
240         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, 
241                     in, out, 
242                     qbuf, rbuf,
243                     svcctl_io_q_query_status,
244                     svcctl_io_r_query_status, 
245                     WERR_GENERAL_FAILURE );
246         
247         if ( !W_ERROR_IS_OK( out.status ) )
248                 return out.status;
249
250         memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) );
251         
252         return out.status;
253 }
254
255 /*******************************************************************
256 *******************************************************************/
257
258 WERROR rpccli_svcctl_query_config(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
259                                 POLICY_HND *hService, SERVICE_CONFIG *config )
260 {
261         SVCCTL_Q_QUERY_SERVICE_CONFIG in;
262         SVCCTL_R_QUERY_SERVICE_CONFIG out;
263         prs_struct qbuf, rbuf;
264         
265         ZERO_STRUCT(in);
266         ZERO_STRUCT(out);
267         
268         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
269         in.buffer_size = 0;
270         
271         
272         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, 
273                     in, out, 
274                     qbuf, rbuf,
275                     svcctl_io_q_query_service_config,
276                     svcctl_io_r_query_service_config, 
277                     WERR_GENERAL_FAILURE );
278         
279         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
280                 in.buffer_size = out.needed;
281
282                 CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W,
283                             in, out, 
284                             qbuf, rbuf,
285                             svcctl_io_q_query_service_config,
286                             svcctl_io_r_query_service_config, 
287                             WERR_GENERAL_FAILURE );
288         }
289         
290         if ( !W_ERROR_IS_OK( out.status ) )
291                 return out.status;
292
293         memcpy( config, &out.config, sizeof(SERVICE_CONFIG) );
294         
295         config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
296         config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
297         config->dependencies   = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
298         config->startname      = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
299         config->displayname    = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
300         
301         if ( out.config.executablepath ) {
302                 config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
303                 copy_unistr2( config->executablepath, out.config.executablepath );
304         }
305
306         if ( out.config.loadordergroup ) {
307                 config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
308                 copy_unistr2( config->loadordergroup, out.config.loadordergroup );
309         }
310
311         if ( out.config.dependencies ) {
312                 config->dependencies = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
313                 copy_unistr2( config->dependencies, out.config.dependencies );
314         }
315
316         if ( out.config.startname ) {
317                 config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
318                 copy_unistr2( config->startname, out.config.startname );
319         }
320
321         if ( out.config.displayname ) {
322                 config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
323                 copy_unistr2( config->displayname, out.config.displayname );
324         }
325         
326         return out.status;
327 }
328
329 /*******************************************************************
330 *******************************************************************/
331
332 WERROR rpccli_svcctl_start_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
333                                  POLICY_HND *hService,
334                                  const char **parm_array, uint32 parmcount )
335 {
336         SVCCTL_Q_START_SERVICE in;
337         SVCCTL_R_START_SERVICE out;
338         prs_struct qbuf, rbuf;
339         
340         ZERO_STRUCT(in);
341         ZERO_STRUCT(out);
342         
343         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
344         
345         in.parmcount  = 0;
346         in.parameters = NULL;
347         
348         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W,
349                     in, out, 
350                     qbuf, rbuf,
351                     svcctl_io_q_start_service,
352                     svcctl_io_r_start_service,
353                     WERR_GENERAL_FAILURE );
354         
355         return out.status;
356 }
357
358 /*******************************************************************
359 *******************************************************************/
360
361 WERROR rpccli_svcctl_control_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
362                                    POLICY_HND *hService, uint32 control,
363                                    SERVICE_STATUS *status )
364 {
365         SVCCTL_Q_CONTROL_SERVICE in;
366         SVCCTL_R_CONTROL_SERVICE out;
367         prs_struct qbuf, rbuf;
368         
369         ZERO_STRUCT(in);
370         ZERO_STRUCT(out);
371         
372         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
373         in.control = control;
374         
375         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, 
376                     in, out, 
377                     qbuf, rbuf,
378                     svcctl_io_q_control_service,
379                     svcctl_io_r_control_service,
380                     WERR_GENERAL_FAILURE );
381         
382         if ( !W_ERROR_IS_OK( out.status ) )
383                 return out.status;
384
385         memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) );
386         
387         return out.status;
388 }
389
390
391 /*******************************************************************
392 *******************************************************************/
393
394 WERROR rpccli_svcctl_get_dispname( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
395                                 POLICY_HND *hService, fstring displayname )
396 {
397         SVCCTL_Q_GET_DISPLAY_NAME in;
398         SVCCTL_R_GET_DISPLAY_NAME out;
399         prs_struct qbuf, rbuf;
400         
401         ZERO_STRUCT(in);
402         ZERO_STRUCT(out);
403         
404         memcpy( &in.handle, hService, sizeof(POLICY_HND) );
405         in.display_name_len = 0;
406         
407         CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
408                     in, out, 
409                     qbuf, rbuf,
410                     svcctl_io_q_get_display_name,
411                     svcctl_io_r_get_display_name, 
412                     WERR_GENERAL_FAILURE );
413         
414         /* second time with correct buffer size...should be ok */
415         
416         if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
417                 in.display_name_len = out.display_name_len;
418
419                 CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
420                             in, out, 
421                             qbuf, rbuf,
422                             svcctl_io_q_get_display_name,
423                             svcctl_io_r_get_display_name, 
424                             WERR_GENERAL_FAILURE );
425         }
426
427         if ( !W_ERROR_IS_OK( out.status ) )
428                 return out.status;
429
430         rpcstr_pull( displayname, out.displayname.buffer, sizeof(displayname), -1, STR_TERMINATE );
431         
432         return out.status;
433 }