[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / libmsrpc / cac_svcctl.c
blob3d3034df15c51693b9c1830746cb5c7326be6dfe
2 /*
3 * Unix SMB/CIFS implementation.
4 * MS-RPC client library implementation (SVCCTL pipe)
5 * Copyright (C) Chris Nicholls 2005.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libmsrpc.h"
23 #include "libsmb_internal.h"
25 #define WAIT_SLEEP_TIME 300000
27 int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
28 POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
29 SERVICE_STATUS * status );
31 int cac_SvcOpenScm( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
32 struct SvcOpenScm *op )
34 SMBCSRV *srv = NULL;
35 struct rpc_pipe_client *pipe_hnd = NULL;
36 WERROR err;
38 POLICY_HND *scm_out = NULL;
40 if ( !hnd )
41 return CAC_FAILURE;
43 if ( !hnd->_internal.ctx ) {
44 hnd->status = NT_STATUS_INVALID_HANDLE;
45 return CAC_FAILURE;
48 if ( !op || op->in.access == 0 || !mem_ctx ) {
49 hnd->status = NT_STATUS_INVALID_PARAMETER;
50 return CAC_FAILURE;
53 srv = cac_GetServer( hnd );
54 if ( !srv ) {
55 hnd->status = NT_STATUS_INVALID_CONNECTION;
56 return CAC_FAILURE;
59 /*initialize for samr pipe if we have to */
60 if ( !hnd->_internal.pipes[PI_SVCCTL] ) {
61 if ( !
62 ( pipe_hnd =
63 cli_rpc_pipe_open_noauth( srv->cli, PI_SVCCTL,
64 &( hnd->status ) ) ) ) {
65 hnd->status = NT_STATUS_UNSUCCESSFUL;
66 return CAC_FAILURE;
69 hnd->_internal.pipes[PI_SVCCTL] = True;
72 scm_out = talloc( mem_ctx, POLICY_HND );
73 if ( !scm_out ) {
74 hnd->status = NT_STATUS_NO_MEMORY;
75 return CAC_FAILURE;
78 err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out,
79 op->in.access );
80 hnd->status = werror_to_ntstatus( err );
82 if ( !NT_STATUS_IS_OK( hnd->status ) )
83 return CAC_FAILURE;
85 op->out.scm_hnd = scm_out;
87 return CAC_SUCCESS;
90 int cac_SvcClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
91 POLICY_HND * scm_hnd )
93 struct rpc_pipe_client *pipe_hnd = NULL;
94 WERROR err;
96 if ( !hnd )
97 return CAC_FAILURE;
99 if ( !hnd->_internal.ctx ) {
100 hnd->status = NT_STATUS_INVALID_HANDLE;
101 return CAC_FAILURE;
104 if ( !scm_hnd || !mem_ctx ) {
105 hnd->status = NT_STATUS_INVALID_PARAMETER;
106 return CAC_FAILURE;
109 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
110 if ( !pipe_hnd ) {
111 hnd->status = NT_STATUS_INVALID_HANDLE;
112 return CAC_FAILURE;
115 err = rpccli_svcctl_close_service( pipe_hnd, mem_ctx, scm_hnd );
116 hnd->status = werror_to_ntstatus( err );
118 if ( !NT_STATUS_IS_OK( hnd->status ) )
119 return CAC_FAILURE;
121 return CAC_SUCCESS;
124 int cac_SvcEnumServices( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
125 struct SvcEnumServices *op )
127 struct rpc_pipe_client *pipe_hnd = NULL;
128 WERROR err;
130 uint32 type_buf = 0;
131 uint32 state_buf = 0;
133 uint32 num_svc_out = 0;
135 ENUM_SERVICES_STATUS *svc_buf = NULL;
137 if ( !hnd )
138 return CAC_FAILURE;
140 if ( !hnd->_internal.ctx ) {
141 hnd->status = NT_STATUS_INVALID_HANDLE;
142 return CAC_FAILURE;
145 if ( !op || !op->in.scm_hnd || !mem_ctx ) {
146 hnd->status = NT_STATUS_INVALID_PARAMETER;
147 return CAC_FAILURE;
150 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
151 if ( !pipe_hnd ) {
152 hnd->status = NT_STATUS_INVALID_HANDLE;
153 return CAC_FAILURE;
156 type_buf =
157 ( op->in.type !=
158 0 ) ? op->in.
159 type : ( SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32 );
160 state_buf = ( op->in.state != 0 ) ? op->in.state : SVCCTL_STATE_ALL;
162 err = rpccli_svcctl_enumerate_services( pipe_hnd, mem_ctx,
163 op->in.scm_hnd, type_buf,
164 state_buf, &num_svc_out,
165 &svc_buf );
166 hnd->status = werror_to_ntstatus( err );
168 if ( !NT_STATUS_IS_OK( hnd->status ) )
169 return CAC_FAILURE;
171 op->out.services =
172 cac_MakeServiceArray( mem_ctx, svc_buf, num_svc_out );
174 if ( !op->out.services ) {
175 hnd->status = NT_STATUS_NO_MEMORY;
176 return CAC_FAILURE;
179 TALLOC_FREE( svc_buf );
181 op->out.num_services = num_svc_out;
183 return CAC_SUCCESS;
186 int cac_SvcOpenService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
187 struct SvcOpenService *op )
189 struct rpc_pipe_client *pipe_hnd = NULL;
190 WERROR err;
192 POLICY_HND *svc_hnd_out = NULL;
194 if ( !hnd )
195 return CAC_FAILURE;
197 if ( !hnd->_internal.ctx ) {
198 hnd->status = NT_STATUS_INVALID_HANDLE;
199 return CAC_FAILURE;
202 if ( !op || !op->in.scm_hnd || !op->in.name || !mem_ctx ) {
203 hnd->status = NT_STATUS_INVALID_PARAMETER;
204 return CAC_FAILURE;
207 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
208 if ( !pipe_hnd ) {
209 hnd->status = NT_STATUS_INVALID_HANDLE;
210 return CAC_FAILURE;
213 svc_hnd_out = talloc( mem_ctx, POLICY_HND );
214 if ( !svc_hnd_out ) {
215 hnd->status = NT_STATUS_NO_MEMORY;
216 return CAC_FAILURE;
219 err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd,
220 svc_hnd_out, op->in.name,
221 op->in.access );
222 hnd->status = werror_to_ntstatus( err );
224 if ( !NT_STATUS_IS_OK( hnd->status ) )
225 return CAC_FAILURE;
227 op->out.svc_hnd = svc_hnd_out;
229 return CAC_SUCCESS;
232 int cac_SvcControlService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
233 struct SvcControlService *op )
235 struct rpc_pipe_client *pipe_hnd = NULL;
236 WERROR err;
238 SERVICE_STATUS status_out;
240 if ( !hnd )
241 return CAC_FAILURE;
243 if ( !hnd->_internal.ctx ) {
244 hnd->status = NT_STATUS_INVALID_HANDLE;
245 return CAC_FAILURE;
248 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
249 hnd->status = NT_STATUS_INVALID_PARAMETER;
250 return CAC_FAILURE;
253 if ( op->in.control < SVCCTL_CONTROL_STOP
254 || op->in.control > SVCCTL_CONTROL_SHUTDOWN ) {
255 hnd->status = NT_STATUS_INVALID_PARAMETER;
256 return CAC_FAILURE;
259 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
260 if ( !pipe_hnd ) {
261 hnd->status = NT_STATUS_INVALID_HANDLE;
262 return CAC_FAILURE;
265 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
266 op->in.svc_hnd, op->in.control,
267 &status_out );
268 hnd->status = werror_to_ntstatus( err );
270 if ( !NT_STATUS_IS_OK( hnd->status ) )
271 return CAC_FAILURE;
273 return CAC_SUCCESS;
276 int cac_SvcGetStatus( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
277 struct SvcGetStatus *op )
279 struct rpc_pipe_client *pipe_hnd = NULL;
280 WERROR err;
282 SERVICE_STATUS status_out;
284 if ( !hnd )
285 return CAC_FAILURE;
287 if ( !hnd->_internal.ctx ) {
288 hnd->status = NT_STATUS_INVALID_HANDLE;
289 return CAC_FAILURE;
292 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
293 hnd->status = NT_STATUS_INVALID_PARAMETER;
294 return CAC_FAILURE;
297 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
298 if ( !pipe_hnd ) {
299 hnd->status = NT_STATUS_INVALID_HANDLE;
300 return CAC_FAILURE;
303 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd,
304 &status_out );
305 hnd->status = werror_to_ntstatus( err );
307 if ( !NT_STATUS_IS_OK( hnd->status ) )
308 return CAC_FAILURE;
310 op->out.status = status_out;
312 return CAC_SUCCESS;
317 /*Internal function - similar to code found in utils/net_rpc_service.c
318 * Waits for a service to reach a specific state.
319 * svc_hnd - Handle to the service
320 * state - the state we are waiting for
321 * timeout - number of seconds to wait
322 * returns CAC_FAILURE if the state is never reached
323 * or CAC_SUCCESS if the state is reached
325 int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
326 POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
327 SERVICE_STATUS * status )
329 struct rpc_pipe_client *pipe_hnd = NULL;
331 /*number of milliseconds we have spent */
332 uint32 time_spent = 0;
333 WERROR err;
335 if ( !hnd || !mem_ctx || !svc_hnd || !status )
336 return CAC_FAILURE;
338 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
339 if ( !pipe_hnd ) {
340 hnd->status = NT_STATUS_INVALID_HANDLE;
341 return CAC_FAILURE;
344 while ( status->state != state && time_spent < ( timeout * 1000000 )
345 && NT_STATUS_IS_OK( hnd->status ) ) {
346 /*if this is the first call, then we _just_ got the status.. sleep now */
347 usleep( WAIT_SLEEP_TIME );
348 time_spent += WAIT_SLEEP_TIME;
350 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, svc_hnd,
351 status );
352 hnd->status = werror_to_ntstatus( err );
355 if ( status->state == state )
356 return CAC_SUCCESS;
358 return CAC_FAILURE;
361 int cac_SvcStartService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
362 struct SvcStartService *op )
364 struct rpc_pipe_client *pipe_hnd = NULL;
365 WERROR err;
367 SERVICE_STATUS status_buf;
369 if ( !hnd )
370 return CAC_FAILURE;
372 if ( !hnd->_internal.ctx ) {
373 hnd->status = NT_STATUS_INVALID_HANDLE;
374 return CAC_FAILURE;
377 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
378 hnd->status = NT_STATUS_INVALID_PARAMETER;
379 return CAC_FAILURE;
382 if ( op->in.num_parms != 0 && op->in.parms == NULL ) {
383 hnd->status = NT_STATUS_INVALID_PARAMETER;
384 return CAC_FAILURE;
387 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
388 if ( !pipe_hnd ) {
389 hnd->status = NT_STATUS_INVALID_HANDLE;
390 return CAC_FAILURE;
393 err = rpccli_svcctl_start_service( pipe_hnd, mem_ctx, op->in.svc_hnd,
394 ( const char ** ) op->in.parms,
395 op->in.num_parms );
396 hnd->status = werror_to_ntstatus( err );
398 if ( !NT_STATUS_IS_OK( hnd->status ) )
399 return CAC_FAILURE;
401 if ( op->in.timeout == 0 )
402 return CAC_SUCCESS;
404 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
405 SVCCTL_RUNNING, op->in.timeout,
406 &status_buf );
409 int cac_SvcStopService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
410 struct SvcStopService *op )
412 struct rpc_pipe_client *pipe_hnd = NULL;
413 WERROR err;
415 SERVICE_STATUS status_out;
417 if ( !hnd )
418 return CAC_FAILURE;
420 if ( !hnd->_internal.ctx ) {
421 hnd->status = NT_STATUS_INVALID_HANDLE;
422 return CAC_FAILURE;
425 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
426 hnd->status = NT_STATUS_INVALID_PARAMETER;
427 return CAC_FAILURE;
430 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
431 if ( !pipe_hnd ) {
432 hnd->status = NT_STATUS_INVALID_HANDLE;
433 return CAC_FAILURE;
436 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
437 op->in.svc_hnd,
438 SVCCTL_CONTROL_STOP,
439 &status_out );
440 hnd->status = werror_to_ntstatus( err );
442 if ( !NT_STATUS_IS_OK( hnd->status ) )
443 return CAC_FAILURE;
445 op->out.status = status_out;
447 if ( op->in.timeout == 0 )
448 return CAC_SUCCESS;
450 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
451 SVCCTL_STOPPED, op->in.timeout,
452 &op->out.status );
455 int cac_SvcPauseService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
456 struct SvcPauseService *op )
458 struct rpc_pipe_client *pipe_hnd = NULL;
459 WERROR err;
461 SERVICE_STATUS status_out;
463 if ( !hnd )
464 return CAC_FAILURE;
466 if ( !hnd->_internal.ctx ) {
467 hnd->status = NT_STATUS_INVALID_HANDLE;
468 return CAC_FAILURE;
471 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
472 hnd->status = NT_STATUS_INVALID_PARAMETER;
473 return CAC_FAILURE;
476 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
477 if ( !pipe_hnd ) {
478 hnd->status = NT_STATUS_INVALID_HANDLE;
479 return CAC_FAILURE;
482 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
483 op->in.svc_hnd,
484 SVCCTL_CONTROL_PAUSE,
485 &status_out );
486 hnd->status = werror_to_ntstatus( err );
488 if ( !NT_STATUS_IS_OK( hnd->status ) )
489 return CAC_FAILURE;
491 op->out.status = status_out;
493 if ( op->in.timeout == 0 )
494 return CAC_SUCCESS;
496 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
497 SVCCTL_PAUSED, op->in.timeout,
498 &op->out.status );
501 int cac_SvcContinueService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
502 struct SvcContinueService *op )
504 struct rpc_pipe_client *pipe_hnd = NULL;
505 WERROR err;
507 SERVICE_STATUS status_out;
509 if ( !hnd )
510 return CAC_FAILURE;
512 if ( !hnd->_internal.ctx ) {
513 hnd->status = NT_STATUS_INVALID_HANDLE;
514 return CAC_FAILURE;
517 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
518 hnd->status = NT_STATUS_INVALID_PARAMETER;
519 return CAC_FAILURE;
522 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
523 if ( !pipe_hnd ) {
524 hnd->status = NT_STATUS_INVALID_HANDLE;
525 return CAC_FAILURE;
528 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
529 op->in.svc_hnd,
530 SVCCTL_CONTROL_CONTINUE,
531 &status_out );
532 hnd->status = werror_to_ntstatus( err );
534 if ( !NT_STATUS_IS_OK( hnd->status ) )
535 return CAC_FAILURE;
537 op->out.status = status_out;
539 if ( op->in.timeout == 0 )
540 return CAC_SUCCESS;
542 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
543 SVCCTL_RUNNING, op->in.timeout,
544 &op->out.status );
547 int cac_SvcGetDisplayName( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
548 struct SvcGetDisplayName *op )
550 struct rpc_pipe_client *pipe_hnd = NULL;
551 WERROR err;
553 fstring disp_name_out;
555 if ( !hnd )
556 return CAC_FAILURE;
558 if ( !hnd->_internal.ctx ) {
559 hnd->status = NT_STATUS_INVALID_HANDLE;
560 return CAC_FAILURE;
563 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
564 hnd->status = NT_STATUS_INVALID_PARAMETER;
565 return CAC_FAILURE;
568 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
569 if ( !pipe_hnd ) {
570 hnd->status = NT_STATUS_INVALID_HANDLE;
571 return CAC_FAILURE;
574 err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd,
575 disp_name_out );
576 hnd->status = werror_to_ntstatus( err );
578 if ( !NT_STATUS_IS_OK( hnd->status ) )
579 return CAC_FAILURE;
581 op->out.display_name = talloc_strdup( mem_ctx, disp_name_out );
583 if ( !op->out.display_name ) {
584 hnd->status = NT_STATUS_NO_MEMORY;
585 return CAC_FAILURE;
588 return CAC_SUCCESS;
592 int cac_SvcGetServiceConfig( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
593 struct SvcGetServiceConfig *op )
595 struct rpc_pipe_client *pipe_hnd = NULL;
596 WERROR err;
598 SERVICE_CONFIG config_out;
600 if ( !hnd )
601 return CAC_FAILURE;
603 if ( !hnd->_internal.ctx ) {
604 hnd->status = NT_STATUS_INVALID_HANDLE;
605 return CAC_FAILURE;
608 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
609 hnd->status = NT_STATUS_INVALID_PARAMETER;
610 return CAC_FAILURE;
613 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
614 if ( !pipe_hnd ) {
615 hnd->status = NT_STATUS_INVALID_HANDLE;
616 return CAC_FAILURE;
619 err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd,
620 &config_out );
621 hnd->status = werror_to_ntstatus( err );
623 if ( !NT_STATUS_IS_OK( hnd->status ) )
624 return CAC_FAILURE;
626 if ( !cac_InitCacServiceConfig
627 ( mem_ctx, &config_out, &op->out.config ) ) {
628 hnd->status = NT_STATUS_NO_MEMORY;
629 return CAC_FAILURE;
632 return CAC_SUCCESS;