3 * Unix SMB/CIFS implementation.
4 * MS-RPC client library implementation (SVCCTL pipe)
5 * Copyright (C) Chris Nicholls 2005.
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.
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 )
35 struct rpc_pipe_client *pipe_hnd = NULL;
38 POLICY_HND *scm_out = NULL;
43 if ( !hnd->_internal.ctx ) {
44 hnd->status = NT_STATUS_INVALID_HANDLE;
48 if ( !op || op->in.access == 0 || !mem_ctx ) {
49 hnd->status = NT_STATUS_INVALID_PARAMETER;
53 srv = cac_GetServer( hnd );
55 hnd->status = NT_STATUS_INVALID_CONNECTION;
59 /*initialize for samr pipe if we have to */
60 if ( !hnd->_internal.pipes[PI_SVCCTL] ) {
63 cli_rpc_pipe_open_noauth( srv->cli, PI_SVCCTL,
64 &( hnd->status ) ) ) ) {
65 hnd->status = NT_STATUS_UNSUCCESSFUL;
69 hnd->_internal.pipes[PI_SVCCTL] = True;
72 scm_out = talloc( mem_ctx, POLICY_HND );
74 hnd->status = NT_STATUS_NO_MEMORY;
78 err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out,
80 hnd->status = werror_to_ntstatus( err );
82 if ( !NT_STATUS_IS_OK( hnd->status ) )
85 op->out.scm_hnd = scm_out;
90 int cac_SvcClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
91 POLICY_HND * scm_hnd )
93 struct rpc_pipe_client *pipe_hnd = NULL;
99 if ( !hnd->_internal.ctx ) {
100 hnd->status = NT_STATUS_INVALID_HANDLE;
104 if ( !scm_hnd || !mem_ctx ) {
105 hnd->status = NT_STATUS_INVALID_PARAMETER;
109 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
111 hnd->status = NT_STATUS_INVALID_HANDLE;
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 ) )
124 int cac_SvcEnumServices( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
125 struct SvcEnumServices *op )
127 struct rpc_pipe_client *pipe_hnd = NULL;
131 uint32 state_buf = 0;
133 uint32 num_svc_out = 0;
135 ENUM_SERVICES_STATUS *svc_buf = NULL;
140 if ( !hnd->_internal.ctx ) {
141 hnd->status = NT_STATUS_INVALID_HANDLE;
145 if ( !op || !op->in.scm_hnd || !mem_ctx ) {
146 hnd->status = NT_STATUS_INVALID_PARAMETER;
150 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
152 hnd->status = NT_STATUS_INVALID_HANDLE;
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,
166 hnd->status = werror_to_ntstatus( err );
168 if ( !NT_STATUS_IS_OK( hnd->status ) )
172 cac_MakeServiceArray( mem_ctx, svc_buf, num_svc_out );
174 if ( !op->out.services ) {
175 hnd->status = NT_STATUS_NO_MEMORY;
179 TALLOC_FREE( svc_buf );
181 op->out.num_services = num_svc_out;
186 int cac_SvcOpenService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
187 struct SvcOpenService *op )
189 struct rpc_pipe_client *pipe_hnd = NULL;
192 POLICY_HND *svc_hnd_out = NULL;
197 if ( !hnd->_internal.ctx ) {
198 hnd->status = NT_STATUS_INVALID_HANDLE;
202 if ( !op || !op->in.scm_hnd || !op->in.name || !mem_ctx ) {
203 hnd->status = NT_STATUS_INVALID_PARAMETER;
207 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
209 hnd->status = NT_STATUS_INVALID_HANDLE;
213 svc_hnd_out = talloc( mem_ctx, POLICY_HND );
214 if ( !svc_hnd_out ) {
215 hnd->status = NT_STATUS_NO_MEMORY;
219 err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd,
220 svc_hnd_out, op->in.name,
222 hnd->status = werror_to_ntstatus( err );
224 if ( !NT_STATUS_IS_OK( hnd->status ) )
227 op->out.svc_hnd = svc_hnd_out;
232 int cac_SvcControlService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
233 struct SvcControlService *op )
235 struct rpc_pipe_client *pipe_hnd = NULL;
238 SERVICE_STATUS status_out;
243 if ( !hnd->_internal.ctx ) {
244 hnd->status = NT_STATUS_INVALID_HANDLE;
248 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
249 hnd->status = NT_STATUS_INVALID_PARAMETER;
253 if ( op->in.control < SVCCTL_CONTROL_STOP
254 || op->in.control > SVCCTL_CONTROL_SHUTDOWN ) {
255 hnd->status = NT_STATUS_INVALID_PARAMETER;
259 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
261 hnd->status = NT_STATUS_INVALID_HANDLE;
265 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
266 op->in.svc_hnd, op->in.control,
268 hnd->status = werror_to_ntstatus( err );
270 if ( !NT_STATUS_IS_OK( hnd->status ) )
276 int cac_SvcGetStatus( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
277 struct SvcGetStatus *op )
279 struct rpc_pipe_client *pipe_hnd = NULL;
282 SERVICE_STATUS status_out;
287 if ( !hnd->_internal.ctx ) {
288 hnd->status = NT_STATUS_INVALID_HANDLE;
292 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
293 hnd->status = NT_STATUS_INVALID_PARAMETER;
297 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
299 hnd->status = NT_STATUS_INVALID_HANDLE;
303 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd,
305 hnd->status = werror_to_ntstatus( err );
307 if ( !NT_STATUS_IS_OK( hnd->status ) )
310 op->out.status = status_out;
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;
335 if ( !hnd || !mem_ctx || !svc_hnd || !status )
338 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
340 hnd->status = NT_STATUS_INVALID_HANDLE;
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,
352 hnd->status = werror_to_ntstatus( err );
355 if ( status->state == state )
361 int cac_SvcStartService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
362 struct SvcStartService *op )
364 struct rpc_pipe_client *pipe_hnd = NULL;
367 SERVICE_STATUS status_buf;
372 if ( !hnd->_internal.ctx ) {
373 hnd->status = NT_STATUS_INVALID_HANDLE;
377 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
378 hnd->status = NT_STATUS_INVALID_PARAMETER;
382 if ( op->in.num_parms != 0 && op->in.parms == NULL ) {
383 hnd->status = NT_STATUS_INVALID_PARAMETER;
387 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
389 hnd->status = NT_STATUS_INVALID_HANDLE;
393 err = rpccli_svcctl_start_service( pipe_hnd, mem_ctx, op->in.svc_hnd,
394 ( const char ** ) op->in.parms,
396 hnd->status = werror_to_ntstatus( err );
398 if ( !NT_STATUS_IS_OK( hnd->status ) )
401 if ( op->in.timeout == 0 )
404 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
405 SVCCTL_RUNNING, op->in.timeout,
409 int cac_SvcStopService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
410 struct SvcStopService *op )
412 struct rpc_pipe_client *pipe_hnd = NULL;
415 SERVICE_STATUS status_out;
420 if ( !hnd->_internal.ctx ) {
421 hnd->status = NT_STATUS_INVALID_HANDLE;
425 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
426 hnd->status = NT_STATUS_INVALID_PARAMETER;
430 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
432 hnd->status = NT_STATUS_INVALID_HANDLE;
436 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
440 hnd->status = werror_to_ntstatus( err );
442 if ( !NT_STATUS_IS_OK( hnd->status ) )
445 op->out.status = status_out;
447 if ( op->in.timeout == 0 )
450 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
451 SVCCTL_STOPPED, op->in.timeout,
455 int cac_SvcPauseService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
456 struct SvcPauseService *op )
458 struct rpc_pipe_client *pipe_hnd = NULL;
461 SERVICE_STATUS status_out;
466 if ( !hnd->_internal.ctx ) {
467 hnd->status = NT_STATUS_INVALID_HANDLE;
471 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
472 hnd->status = NT_STATUS_INVALID_PARAMETER;
476 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
478 hnd->status = NT_STATUS_INVALID_HANDLE;
482 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
484 SVCCTL_CONTROL_PAUSE,
486 hnd->status = werror_to_ntstatus( err );
488 if ( !NT_STATUS_IS_OK( hnd->status ) )
491 op->out.status = status_out;
493 if ( op->in.timeout == 0 )
496 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
497 SVCCTL_PAUSED, op->in.timeout,
501 int cac_SvcContinueService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
502 struct SvcContinueService *op )
504 struct rpc_pipe_client *pipe_hnd = NULL;
507 SERVICE_STATUS status_out;
512 if ( !hnd->_internal.ctx ) {
513 hnd->status = NT_STATUS_INVALID_HANDLE;
517 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
518 hnd->status = NT_STATUS_INVALID_PARAMETER;
522 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
524 hnd->status = NT_STATUS_INVALID_HANDLE;
528 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
530 SVCCTL_CONTROL_CONTINUE,
532 hnd->status = werror_to_ntstatus( err );
534 if ( !NT_STATUS_IS_OK( hnd->status ) )
537 op->out.status = status_out;
539 if ( op->in.timeout == 0 )
542 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
543 SVCCTL_RUNNING, op->in.timeout,
547 int cac_SvcGetDisplayName( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
548 struct SvcGetDisplayName *op )
550 struct rpc_pipe_client *pipe_hnd = NULL;
553 fstring disp_name_out;
558 if ( !hnd->_internal.ctx ) {
559 hnd->status = NT_STATUS_INVALID_HANDLE;
563 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
564 hnd->status = NT_STATUS_INVALID_PARAMETER;
568 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
570 hnd->status = NT_STATUS_INVALID_HANDLE;
574 err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd,
576 hnd->status = werror_to_ntstatus( err );
578 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
592 int cac_SvcGetServiceConfig( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
593 struct SvcGetServiceConfig *op )
595 struct rpc_pipe_client *pipe_hnd = NULL;
598 SERVICE_CONFIG config_out;
603 if ( !hnd->_internal.ctx ) {
604 hnd->status = NT_STATUS_INVALID_HANDLE;
608 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
609 hnd->status = NT_STATUS_INVALID_PARAMETER;
613 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
615 hnd->status = NT_STATUS_INVALID_HANDLE;
619 err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd,
621 hnd->status = werror_to_ntstatus( err );
623 if ( !NT_STATUS_IS_OK( hnd->status ) )
626 if ( !cac_InitCacServiceConfig
627 ( mem_ctx, &config_out, &op->out.config ) ) {
628 hnd->status = NT_STATUS_NO_MEMORY;