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 3 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, see <http://www.gnu.org/licenses/>.
22 #include "libsmb_internal.h"
24 #define WAIT_SLEEP_TIME 300000
26 int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
27 POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
28 SERVICE_STATUS * status );
30 int cac_SvcOpenScm( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
31 struct SvcOpenScm *op )
34 struct rpc_pipe_client *pipe_hnd = NULL;
37 POLICY_HND *scm_out = NULL;
42 if ( !hnd->_internal.ctx ) {
43 hnd->status = NT_STATUS_INVALID_HANDLE;
47 if ( !op || op->in.access == 0 || !mem_ctx ) {
48 hnd->status = NT_STATUS_INVALID_PARAMETER;
52 srv = cac_GetServer( hnd );
54 hnd->status = NT_STATUS_INVALID_CONNECTION;
58 /*initialize for samr pipe if we have to */
59 if ( !hnd->_internal.pipes[PI_SVCCTL] ) {
62 cli_rpc_pipe_open_noauth( srv->cli, PI_SVCCTL,
63 &( hnd->status ) ) ) ) {
64 hnd->status = NT_STATUS_UNSUCCESSFUL;
68 hnd->_internal.pipes[PI_SVCCTL] = True;
71 scm_out = talloc( mem_ctx, POLICY_HND );
73 hnd->status = NT_STATUS_NO_MEMORY;
77 err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out,
79 hnd->status = werror_to_ntstatus( err );
81 if ( !NT_STATUS_IS_OK( hnd->status ) )
84 op->out.scm_hnd = scm_out;
89 int cac_SvcClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
90 POLICY_HND * scm_hnd )
92 struct rpc_pipe_client *pipe_hnd = NULL;
97 if ( !hnd->_internal.ctx ) {
98 hnd->status = NT_STATUS_INVALID_HANDLE;
102 if ( !scm_hnd || !mem_ctx ) {
103 hnd->status = NT_STATUS_INVALID_PARAMETER;
107 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
109 hnd->status = NT_STATUS_INVALID_HANDLE;
113 hnd->status = rpccli_svcctl_CloseServiceHandle( pipe_hnd, mem_ctx, scm_hnd );
115 if ( !NT_STATUS_IS_OK( hnd->status ) )
121 int cac_SvcEnumServices( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
122 struct SvcEnumServices *op )
124 struct rpc_pipe_client *pipe_hnd = NULL;
128 uint32 state_buf = 0;
130 uint32 num_svc_out = 0;
132 ENUM_SERVICES_STATUS *svc_buf = NULL;
137 if ( !hnd->_internal.ctx ) {
138 hnd->status = NT_STATUS_INVALID_HANDLE;
142 if ( !op || !op->in.scm_hnd || !mem_ctx ) {
143 hnd->status = NT_STATUS_INVALID_PARAMETER;
147 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
149 hnd->status = NT_STATUS_INVALID_HANDLE;
156 type : ( SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32 );
157 state_buf = ( op->in.state != 0 ) ? op->in.state : SVCCTL_STATE_ALL;
159 err = rpccli_svcctl_enumerate_services( pipe_hnd, mem_ctx,
160 op->in.scm_hnd, type_buf,
161 state_buf, &num_svc_out,
163 hnd->status = werror_to_ntstatus( err );
165 if ( !NT_STATUS_IS_OK( hnd->status ) )
169 cac_MakeServiceArray( mem_ctx, svc_buf, num_svc_out );
171 if ( !op->out.services ) {
172 hnd->status = NT_STATUS_NO_MEMORY;
176 TALLOC_FREE( svc_buf );
178 op->out.num_services = num_svc_out;
183 int cac_SvcOpenService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
184 struct SvcOpenService *op )
186 struct rpc_pipe_client *pipe_hnd = NULL;
189 POLICY_HND *svc_hnd_out = NULL;
194 if ( !hnd->_internal.ctx ) {
195 hnd->status = NT_STATUS_INVALID_HANDLE;
199 if ( !op || !op->in.scm_hnd || !op->in.name || !mem_ctx ) {
200 hnd->status = NT_STATUS_INVALID_PARAMETER;
204 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
206 hnd->status = NT_STATUS_INVALID_HANDLE;
210 svc_hnd_out = talloc( mem_ctx, POLICY_HND );
211 if ( !svc_hnd_out ) {
212 hnd->status = NT_STATUS_NO_MEMORY;
216 err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd,
217 svc_hnd_out, op->in.name,
219 hnd->status = werror_to_ntstatus( err );
221 if ( !NT_STATUS_IS_OK( hnd->status ) )
224 op->out.svc_hnd = svc_hnd_out;
229 int cac_SvcControlService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
230 struct SvcControlService *op )
232 struct rpc_pipe_client *pipe_hnd = NULL;
235 SERVICE_STATUS status_out;
240 if ( !hnd->_internal.ctx ) {
241 hnd->status = NT_STATUS_INVALID_HANDLE;
245 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
246 hnd->status = NT_STATUS_INVALID_PARAMETER;
250 if ( op->in.control < SVCCTL_CONTROL_STOP
251 || op->in.control > SVCCTL_CONTROL_SHUTDOWN ) {
252 hnd->status = NT_STATUS_INVALID_PARAMETER;
256 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
258 hnd->status = NT_STATUS_INVALID_HANDLE;
262 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
263 op->in.svc_hnd, op->in.control,
265 hnd->status = werror_to_ntstatus( err );
267 if ( !NT_STATUS_IS_OK( hnd->status ) )
273 int cac_SvcGetStatus( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
274 struct SvcGetStatus *op )
276 struct rpc_pipe_client *pipe_hnd = NULL;
279 SERVICE_STATUS status_out;
284 if ( !hnd->_internal.ctx ) {
285 hnd->status = NT_STATUS_INVALID_HANDLE;
289 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
290 hnd->status = NT_STATUS_INVALID_PARAMETER;
294 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
296 hnd->status = NT_STATUS_INVALID_HANDLE;
300 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd,
302 hnd->status = werror_to_ntstatus( err );
304 if ( !NT_STATUS_IS_OK( hnd->status ) )
307 op->out.status = status_out;
314 /*Internal function - similar to code found in utils/net_rpc_service.c
315 * Waits for a service to reach a specific state.
316 * svc_hnd - Handle to the service
317 * state - the state we are waiting for
318 * timeout - number of seconds to wait
319 * returns CAC_FAILURE if the state is never reached
320 * or CAC_SUCCESS if the state is reached
322 int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
323 POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
324 SERVICE_STATUS * status )
326 struct rpc_pipe_client *pipe_hnd = NULL;
328 /*number of milliseconds we have spent */
329 uint32 time_spent = 0;
332 if ( !hnd || !mem_ctx || !svc_hnd || !status )
335 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
337 hnd->status = NT_STATUS_INVALID_HANDLE;
341 while ( status->state != state && time_spent < ( timeout * 1000000 )
342 && NT_STATUS_IS_OK( hnd->status ) ) {
343 /*if this is the first call, then we _just_ got the status.. sleep now */
344 usleep( WAIT_SLEEP_TIME );
345 time_spent += WAIT_SLEEP_TIME;
347 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, svc_hnd,
349 hnd->status = werror_to_ntstatus( err );
352 if ( status->state == state )
358 int cac_SvcStartService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
359 struct SvcStartService *op )
361 struct rpc_pipe_client *pipe_hnd = NULL;
364 SERVICE_STATUS status_buf;
369 if ( !hnd->_internal.ctx ) {
370 hnd->status = NT_STATUS_INVALID_HANDLE;
374 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
375 hnd->status = NT_STATUS_INVALID_PARAMETER;
379 if ( op->in.num_parms != 0 && op->in.parms == NULL ) {
380 hnd->status = NT_STATUS_INVALID_PARAMETER;
384 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
386 hnd->status = NT_STATUS_INVALID_HANDLE;
390 err = rpccli_svcctl_start_service( pipe_hnd, mem_ctx, op->in.svc_hnd,
391 ( const char ** ) op->in.parms,
393 hnd->status = werror_to_ntstatus( err );
395 if ( !NT_STATUS_IS_OK( hnd->status ) )
398 if ( op->in.timeout == 0 )
401 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
402 SVCCTL_RUNNING, op->in.timeout,
406 int cac_SvcStopService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
407 struct SvcStopService *op )
409 struct rpc_pipe_client *pipe_hnd = NULL;
412 SERVICE_STATUS status_out;
417 if ( !hnd->_internal.ctx ) {
418 hnd->status = NT_STATUS_INVALID_HANDLE;
422 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
423 hnd->status = NT_STATUS_INVALID_PARAMETER;
427 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
429 hnd->status = NT_STATUS_INVALID_HANDLE;
433 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
437 hnd->status = werror_to_ntstatus( err );
439 if ( !NT_STATUS_IS_OK( hnd->status ) )
442 op->out.status = status_out;
444 if ( op->in.timeout == 0 )
447 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
448 SVCCTL_STOPPED, op->in.timeout,
452 int cac_SvcPauseService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
453 struct SvcPauseService *op )
455 struct rpc_pipe_client *pipe_hnd = NULL;
458 SERVICE_STATUS status_out;
463 if ( !hnd->_internal.ctx ) {
464 hnd->status = NT_STATUS_INVALID_HANDLE;
468 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
469 hnd->status = NT_STATUS_INVALID_PARAMETER;
473 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
475 hnd->status = NT_STATUS_INVALID_HANDLE;
479 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
481 SVCCTL_CONTROL_PAUSE,
483 hnd->status = werror_to_ntstatus( err );
485 if ( !NT_STATUS_IS_OK( hnd->status ) )
488 op->out.status = status_out;
490 if ( op->in.timeout == 0 )
493 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
494 SVCCTL_PAUSED, op->in.timeout,
498 int cac_SvcContinueService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
499 struct SvcContinueService *op )
501 struct rpc_pipe_client *pipe_hnd = NULL;
504 SERVICE_STATUS status_out;
509 if ( !hnd->_internal.ctx ) {
510 hnd->status = NT_STATUS_INVALID_HANDLE;
514 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
515 hnd->status = NT_STATUS_INVALID_PARAMETER;
519 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
521 hnd->status = NT_STATUS_INVALID_HANDLE;
525 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
527 SVCCTL_CONTROL_CONTINUE,
529 hnd->status = werror_to_ntstatus( err );
531 if ( !NT_STATUS_IS_OK( hnd->status ) )
534 op->out.status = status_out;
536 if ( op->in.timeout == 0 )
539 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
540 SVCCTL_RUNNING, op->in.timeout,
544 int cac_SvcGetDisplayName( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
545 struct SvcGetDisplayName *op )
547 struct rpc_pipe_client *pipe_hnd = NULL;
550 fstring disp_name_out;
555 if ( !hnd->_internal.ctx ) {
556 hnd->status = NT_STATUS_INVALID_HANDLE;
560 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
561 hnd->status = NT_STATUS_INVALID_PARAMETER;
565 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
567 hnd->status = NT_STATUS_INVALID_HANDLE;
571 err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd,
573 hnd->status = werror_to_ntstatus( err );
575 if ( !NT_STATUS_IS_OK( hnd->status ) )
578 op->out.display_name = talloc_strdup( mem_ctx, disp_name_out );
580 if ( !op->out.display_name ) {
581 hnd->status = NT_STATUS_NO_MEMORY;
589 int cac_SvcGetServiceConfig( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
590 struct SvcGetServiceConfig *op )
592 struct rpc_pipe_client *pipe_hnd = NULL;
595 SERVICE_CONFIG config_out;
600 if ( !hnd->_internal.ctx ) {
601 hnd->status = NT_STATUS_INVALID_HANDLE;
605 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
606 hnd->status = NT_STATUS_INVALID_PARAMETER;
610 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
612 hnd->status = NT_STATUS_INVALID_HANDLE;
616 err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd,
618 hnd->status = werror_to_ntstatus( err );
620 if ( !NT_STATUS_IS_OK( hnd->status ) )
623 if ( !cac_InitCacServiceConfig
624 ( mem_ctx, &config_out, &op->out.config ) ) {
625 hnd->status = NT_STATUS_NO_MEMORY;