2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Marcin Krzysztof Porwit 2005.
7 * Largely Rewritten (Again) by:
8 * Copyright (C) Gerald (Jerry) Carter 2005.
9 * Copyright (C) Guenther Deschner 2008,2009.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 #include "system/passwd.h" /* uid_wrapper */
28 #include "../libcli/security/security.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
30 #include "services/services.h"
31 #include "services/svc_winreg_glue.h"
33 #include "rpc_server/svcctl/srv_svcctl_nt.h"
35 #include "rpc_server/rpc_server.h"
36 #include "librpc/rpc/dcesrv_core.h"
37 #include "librpc/gen_ndr/ndr_svcctl.h"
38 #include "librpc/gen_ndr/ndr_svcctl_scompat.h"
39 #include "srv_svcctl_reg.h"
40 #include "lib/global_contexts.h"
43 #define DBGC_CLASS DBGC_RPC_SRV
45 struct service_control_op
{
47 SERVICE_CONTROL_OPS
*ops
;
50 /* handle external services */
51 extern SERVICE_CONTROL_OPS rcinit_svc_ops
;
53 /* builtin services (see service_db.c and services/svc_*.c */
54 extern SERVICE_CONTROL_OPS spoolss_svc_ops
;
55 extern SERVICE_CONTROL_OPS netlogon_svc_ops
;
56 extern SERVICE_CONTROL_OPS winreg_svc_ops
;
57 extern SERVICE_CONTROL_OPS wins_svc_ops
;
59 /* make sure this number patches the number of builtin
60 SERVICE_CONTROL_OPS structure listed above */
62 #define SVCCTL_NUM_INTERNAL_SERVICES 4
64 struct service_control_op
*svcctl_ops
;
66 static const struct generic_mapping scm_generic_map
=
67 { SC_MANAGER_READ_ACCESS
, SC_MANAGER_WRITE_ACCESS
, SC_MANAGER_EXECUTE_ACCESS
, SC_MANAGER_ALL_ACCESS
};
68 static const struct generic_mapping svc_generic_map
=
69 { SERVICE_READ_ACCESS
, SERVICE_WRITE_ACCESS
, SERVICE_EXECUTE_ACCESS
, SERVICE_ALL_ACCESS
};
72 /********************************************************************
73 ********************************************************************/
75 bool init_service_op_table( void )
77 const char **service_list
= lp_svcctl_list();
78 int num_services
= SVCCTL_NUM_INTERNAL_SERVICES
+ str_list_length( service_list
);
81 if ( !(svcctl_ops
= talloc_array( NULL
, struct service_control_op
, num_services
+1)) ) {
82 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
86 /* services listed in smb.conf get the rc.init interface */
88 for ( i
=0; service_list
&& service_list
[i
]; i
++ ) {
89 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, service_list
[i
] );
90 svcctl_ops
[i
].ops
= &rcinit_svc_ops
;
93 /* add builtin services */
95 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "Spooler" );
96 svcctl_ops
[i
].ops
= &spoolss_svc_ops
;
99 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "NETLOGON" );
100 svcctl_ops
[i
].ops
= &netlogon_svc_ops
;
103 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "RemoteRegistry" );
104 svcctl_ops
[i
].ops
= &winreg_svc_ops
;
107 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "WINS" );
108 svcctl_ops
[i
].ops
= &wins_svc_ops
;
111 /* NULL terminate the array */
113 svcctl_ops
[i
].name
= NULL
;
114 svcctl_ops
[i
].ops
= NULL
;
119 bool shutdown_service_op_table(void)
121 TALLOC_FREE(svcctl_ops
);
126 /********************************************************************
127 ********************************************************************/
129 static struct service_control_op
* find_service_by_name( const char *name
)
133 for ( i
=0; svcctl_ops
[i
].name
; i
++ ) {
134 if ( strequal( name
, svcctl_ops
[i
].name
) )
135 return &svcctl_ops
[i
];
140 /********************************************************************
141 ********************************************************************/
143 static NTSTATUS
svcctl_access_check( struct security_descriptor
*sec_desc
, struct security_token
*token
,
144 uint32_t access_desired
, uint32_t *access_granted
)
147 if ( geteuid() == sec_initial_uid() ) {
148 DEBUG(5,("svcctl_access_check: using root's token\n"));
149 status
= get_root_nt_token(&token
);
150 if(!NT_STATUS_IS_OK(status
)) {
155 return se_access_check( sec_desc
, token
, access_desired
, access_granted
);
158 /********************************************************************
159 ********************************************************************/
161 static struct security_descriptor
* construct_scm_sd( TALLOC_CTX
*ctx
)
163 struct security_ace ace
[2] = {};
165 struct security_descriptor
*sd
;
166 struct security_acl
*theacl
;
169 /* basic access for Everyone */
171 init_sec_ace(&ace
[i
++], &global_sid_World
,
172 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_READ_ACCESS
, 0);
174 /* Full Access 'BUILTIN\Administrators' */
176 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
177 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_ALL_ACCESS
, 0);
180 /* create the security descriptor */
182 if ( !(theacl
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) )
185 if ( !(sd
= make_sec_desc(ctx
, SECURITY_DESCRIPTOR_REVISION_1
,
186 SEC_DESC_SELF_RELATIVE
, NULL
, NULL
, NULL
,
193 /******************************************************************
194 Find a registry key handle and return a SERVICE_INFO
195 *****************************************************************/
197 static SERVICE_INFO
*find_service_info_by_hnd(struct pipes_struct
*p
,
198 struct policy_handle
*hnd
)
200 SERVICE_INFO
*service_info
= NULL
;
203 service_info
= find_policy_by_hnd(p
,
208 if (!NT_STATUS_IS_OK(status
)) {
209 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
216 /******************************************************************
217 *****************************************************************/
219 static WERROR
create_open_service_handle(struct pipes_struct
*p
,
220 struct policy_handle
*handle
,
223 uint32_t access_granted
)
225 SERVICE_INFO
*info
= NULL
;
226 WERROR result
= WERR_OK
;
227 struct service_control_op
*s_op
;
229 if ( !(info
= talloc_zero( NULL
, SERVICE_INFO
)) )
230 return WERR_NOT_ENOUGH_MEMORY
;
232 /* the Service Manager has a NULL name */
234 info
->type
= SVC_HANDLE_IS_SCM
;
237 case SVC_HANDLE_IS_SCM
:
238 info
->type
= SVC_HANDLE_IS_SCM
;
241 case SVC_HANDLE_IS_DBLOCK
:
242 info
->type
= SVC_HANDLE_IS_DBLOCK
;
245 case SVC_HANDLE_IS_SERVICE
:
246 info
->type
= SVC_HANDLE_IS_SERVICE
;
248 /* lookup the SERVICE_CONTROL_OPS */
250 if ( !(s_op
= find_service_by_name( service
)) ) {
251 result
= WERR_SERVICE_DOES_NOT_EXIST
;
255 info
->ops
= s_op
->ops
;
257 if ( !(info
->name
= talloc_strdup( info
, s_op
->name
)) ) {
258 result
= WERR_NOT_ENOUGH_MEMORY
;
264 result
= WERR_SERVICE_DOES_NOT_EXIST
;
268 info
->access_granted
= access_granted
;
270 /* store the SERVICE_INFO and create an open handle */
272 if ( !create_policy_hnd( p
, handle
, 0, info
) ) {
273 result
= WERR_ACCESS_DENIED
;
278 if ( !W_ERROR_IS_OK(result
) )
284 /********************************************************************
285 _svcctl_OpenSCManagerW
286 ********************************************************************/
288 WERROR
_svcctl_OpenSCManagerW(struct pipes_struct
*p
,
289 struct svcctl_OpenSCManagerW
*r
)
291 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
292 struct auth_session_info
*session_info
=
293 dcesrv_call_session_info(dce_call
);
294 struct security_descriptor
*sec_desc
;
295 uint32_t access_granted
= 0;
298 /* perform access checks */
300 if ( !(sec_desc
= construct_scm_sd( p
->mem_ctx
)) )
301 return WERR_NOT_ENOUGH_MEMORY
;
303 se_map_generic( &r
->in
.access_mask
, &scm_generic_map
);
304 status
= svcctl_access_check( sec_desc
, session_info
->security_token
,
305 r
->in
.access_mask
, &access_granted
);
306 if ( !NT_STATUS_IS_OK(status
) )
307 return ntstatus_to_werror( status
);
309 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SCM
, NULL
, access_granted
);
312 /********************************************************************
314 ********************************************************************/
316 WERROR
_svcctl_OpenServiceW(struct pipes_struct
*p
,
317 struct svcctl_OpenServiceW
*r
)
319 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
320 struct auth_session_info
*session_info
=
321 dcesrv_call_session_info(dce_call
);
322 struct security_descriptor
*sec_desc
;
323 uint32_t access_granted
= 0;
325 const char *service
= NULL
;
328 service
= r
->in
.ServiceName
;
330 return WERR_NOT_ENOUGH_MEMORY
;
332 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service
));
334 /* based on my tests you can open a service if you have a valid scm handle */
336 if ( !find_service_info_by_hnd( p
, r
->in
.scmanager_handle
) )
337 return WERR_INVALID_HANDLE
;
340 * Perform access checks. Use the system session_info in order to ensure
341 * that we retrieve the security descriptor
343 err
= svcctl_get_secdesc(p
->msg_ctx
,
344 get_session_info_system(),
348 if (W_ERROR_EQUAL(err
, WERR_FILE_NOT_FOUND
)) {
349 DBG_NOTICE("service %s does not exist\n", service
);
350 return WERR_SERVICE_DOES_NOT_EXIST
;
352 if (!W_ERROR_IS_OK(err
)) {
353 DBG_NOTICE("Failed to get a valid secdesc for %s: %s\n",
354 service
, win_errstr(err
));
358 se_map_generic( &r
->in
.access_mask
, &svc_generic_map
);
359 status
= svcctl_access_check( sec_desc
, session_info
->security_token
,
360 r
->in
.access_mask
, &access_granted
);
361 if ( !NT_STATUS_IS_OK(status
) )
362 return ntstatus_to_werror( status
);
364 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SERVICE
, service
, access_granted
);
367 /********************************************************************
368 _svcctl_CloseServiceHandle
369 ********************************************************************/
371 WERROR
_svcctl_CloseServiceHandle(struct pipes_struct
*p
,
372 struct svcctl_CloseServiceHandle
*r
)
374 if ( !close_policy_hnd( p
, r
->in
.handle
) )
375 return WERR_INVALID_HANDLE
;
377 ZERO_STRUCTP(r
->out
.handle
);
382 /********************************************************************
383 _svcctl_GetServiceDisplayNameW
384 ********************************************************************/
386 WERROR
_svcctl_GetServiceDisplayNameW(struct pipes_struct
*p
,
387 struct svcctl_GetServiceDisplayNameW
*r
)
389 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
390 struct auth_session_info
*session_info
=
391 dcesrv_call_session_info(dce_call
);
393 const char *display_name
;
394 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
396 /* can only use an SCM handle here */
398 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
399 return WERR_INVALID_HANDLE
;
401 service
= r
->in
.service_name
;
403 display_name
= svcctl_lookup_dispname(p
->mem_ctx
,
411 *r
->out
.display_name
= display_name
;
412 *r
->out
.display_name_length
= strlen(display_name
);
417 /********************************************************************
418 _svcctl_QueryServiceStatus
419 ********************************************************************/
421 WERROR
_svcctl_QueryServiceStatus(struct pipes_struct
*p
,
422 struct svcctl_QueryServiceStatus
*r
)
424 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
426 /* perform access checks */
428 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
429 return WERR_INVALID_HANDLE
;
431 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
432 return WERR_ACCESS_DENIED
;
434 /* try the service specific status call */
436 return info
->ops
->service_status( info
->name
, r
->out
.service_status
);
439 /********************************************************************
440 ********************************************************************/
442 static int enumerate_status(TALLOC_CTX
*ctx
,
443 struct messaging_context
*msg_ctx
,
444 struct auth_session_info
*session_info
,
445 struct ENUM_SERVICE_STATUSW
**status
)
447 int num_services
= 0;
449 struct ENUM_SERVICE_STATUSW
*st
;
450 const char *display_name
;
453 while ( svcctl_ops
[num_services
].name
)
456 if ( !(st
= talloc_array( ctx
, struct ENUM_SERVICE_STATUSW
, num_services
)) ) {
457 DEBUG(0,("enumerate_status: talloc() failed!\n"));
461 for ( i
=0; i
<num_services
; i
++ ) {
462 st
[i
].service_name
= talloc_strdup(st
, svcctl_ops
[i
].name
);
464 display_name
= svcctl_lookup_dispname(ctx
,
468 st
[i
].display_name
= talloc_strdup(st
, display_name
? display_name
: "");
470 svcctl_ops
[i
].ops
->service_status( svcctl_ops
[i
].name
, &st
[i
].status
);
478 /********************************************************************
479 _svcctl_EnumServicesStatusW
480 ********************************************************************/
482 WERROR
_svcctl_EnumServicesStatusW(struct pipes_struct
*p
,
483 struct svcctl_EnumServicesStatusW
*r
)
485 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
486 struct auth_session_info
*session_info
=
487 dcesrv_call_session_info(dce_call
);
488 struct ENUM_SERVICE_STATUSW
*services
= NULL
;
491 size_t buffer_size
= 0;
492 WERROR result
= WERR_OK
;
493 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
494 DATA_BLOB blob
= data_blob_null
;
496 /* perform access checks */
498 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
499 return WERR_INVALID_HANDLE
;
501 if ( !(info
->access_granted
& SC_RIGHT_MGR_ENUMERATE_SERVICE
) ) {
502 return WERR_ACCESS_DENIED
;
505 num_services
= enumerate_status(p
->mem_ctx
,
509 if (num_services
== -1 ) {
510 return WERR_NOT_ENOUGH_MEMORY
;
513 for ( i
=0; i
<num_services
; i
++ ) {
514 buffer_size
+= ndr_size_ENUM_SERVICE_STATUSW(&services
[i
], 0);
517 buffer_size
+= buffer_size
% 4;
519 if (buffer_size
> r
->in
.offered
) {
521 result
= WERR_MORE_DATA
;
524 if ( W_ERROR_IS_OK(result
) ) {
526 enum ndr_err_code ndr_err
;
527 struct ndr_push
*ndr
;
529 ndr
= ndr_push_init_ctx(p
->mem_ctx
);
531 return WERR_INVALID_PARAMETER
;
534 ndr_err
= ndr_push_ENUM_SERVICE_STATUSW_array(
535 ndr
, num_services
, services
);
536 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
537 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err
));
539 blob
= ndr_push_blob(ndr
);
540 memcpy(r
->out
.service
, blob
.data
, MIN(blob
.length
, r
->in
.offered
));
543 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
544 *r
->out
.services_returned
= (uint32_t)num_services
;
545 if (r
->out
.resume_handle
) {
546 *r
->out
.resume_handle
= 0;
552 /********************************************************************
553 _svcctl_StartServiceW
554 ********************************************************************/
556 WERROR
_svcctl_StartServiceW(struct pipes_struct
*p
,
557 struct svcctl_StartServiceW
*r
)
559 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
561 /* perform access checks */
563 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
564 return WERR_INVALID_HANDLE
;
566 if ( !(info
->access_granted
& SC_RIGHT_SVC_START
) )
567 return WERR_ACCESS_DENIED
;
569 return info
->ops
->start_service( info
->name
);
572 /********************************************************************
573 _svcctl_ControlService
574 ********************************************************************/
576 WERROR
_svcctl_ControlService(struct pipes_struct
*p
,
577 struct svcctl_ControlService
*r
)
579 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
581 /* perform access checks */
583 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
584 return WERR_INVALID_HANDLE
;
586 switch ( r
->in
.control
) {
587 case SVCCTL_CONTROL_STOP
:
588 if ( !(info
->access_granted
& SC_RIGHT_SVC_STOP
) )
589 return WERR_ACCESS_DENIED
;
591 return info
->ops
->stop_service( info
->name
,
592 r
->out
.service_status
);
594 case SVCCTL_CONTROL_INTERROGATE
:
595 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
596 return WERR_ACCESS_DENIED
;
598 return info
->ops
->service_status( info
->name
,
599 r
->out
.service_status
);
601 return WERR_INVALID_PARAMETER
;
605 /********************************************************************
606 _svcctl_EnumDependentServicesW
607 ********************************************************************/
609 WERROR
_svcctl_EnumDependentServicesW(struct pipes_struct
*p
,
610 struct svcctl_EnumDependentServicesW
*r
)
612 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.service
);
614 /* perform access checks */
616 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
617 return WERR_INVALID_HANDLE
;
619 if ( !(info
->access_granted
& SC_RIGHT_SVC_ENUMERATE_DEPENDENTS
) )
620 return WERR_ACCESS_DENIED
;
622 switch (r
->in
.state
) {
623 case SERVICE_STATE_ACTIVE
:
624 case SERVICE_STATE_INACTIVE
:
625 case SERVICE_STATE_ALL
:
628 return WERR_INVALID_PARAMETER
;
631 /* we have to set the outgoing buffer size to the same as the
632 incoming buffer size (even in the case of failure */
633 /* this is done in the autogenerated server already - gd */
635 *r
->out
.needed
= r
->in
.offered
;
637 /* no dependent services...basically a stub function */
638 *r
->out
.services_returned
= 0;
643 /********************************************************************
644 _svcctl_QueryServiceStatusEx
645 ********************************************************************/
647 WERROR
_svcctl_QueryServiceStatusEx(struct pipes_struct
*p
,
648 struct svcctl_QueryServiceStatusEx
*r
)
650 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
651 uint32_t buffer_size
;
653 /* perform access checks */
655 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
656 return WERR_INVALID_HANDLE
;
658 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
659 return WERR_ACCESS_DENIED
;
661 /* we have to set the outgoing buffer size to the same as the
662 incoming buffer size (even in the case of failure) */
663 *r
->out
.needed
= r
->in
.offered
;
665 switch ( r
->in
.info_level
) {
666 case SVC_STATUS_PROCESS_INFO
:
668 struct SERVICE_STATUS_PROCESS svc_stat_proc
;
669 enum ndr_err_code ndr_err
;
672 /* Get the status of the service.. */
673 info
->ops
->service_status( info
->name
, &svc_stat_proc
.status
);
674 svc_stat_proc
.process_id
= getpid();
675 svc_stat_proc
.service_flags
= 0x0;
677 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &svc_stat_proc
,
678 (ndr_push_flags_fn_t
)ndr_push_SERVICE_STATUS_PROCESS
);
679 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
680 return WERR_INVALID_PARAMETER
;
683 r
->out
.buffer
= blob
.data
;
684 buffer_size
= sizeof(struct SERVICE_STATUS_PROCESS
);
689 return WERR_INVALID_LEVEL
;
693 buffer_size
+= buffer_size
% 4;
694 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
696 if (buffer_size
> r
->in
.offered
) {
697 return WERR_INSUFFICIENT_BUFFER
;
703 /********************************************************************
704 ********************************************************************/
706 static WERROR
fill_svc_config(TALLOC_CTX
*mem_ctx
,
707 struct messaging_context
*msg_ctx
,
708 struct auth_session_info
*session_info
,
710 struct QUERY_SERVICE_CONFIG
*config
)
712 const char *result
= NULL
;
714 /* now fill in the individual values */
716 ZERO_STRUCTP(config
);
718 config
->displayname
= svcctl_lookup_dispname(mem_ctx
,
723 result
= svcctl_get_string_value(mem_ctx
,
728 if (result
!= NULL
) {
729 config
->startname
= result
;
732 result
= svcctl_get_string_value(mem_ctx
,
737 if (result
!= NULL
) {
738 config
->executablepath
= result
;
741 /* a few hard coded values */
742 /* loadordergroup and dependencies are empty */
744 config
->tag_id
= 0x00000000; /* unassigned loadorder group */
745 config
->service_type
= SERVICE_TYPE_WIN32_OWN_PROCESS
;
746 config
->error_control
= SVCCTL_SVC_ERROR_NORMAL
;
748 /* set the start type. NetLogon and WINS are disabled to prevent
749 the client from showing the "Start" button (if of course the services
752 if ( strequal( name
, "NETLOGON" ) && ( lp_servicenumber(name
) == -1 ) )
753 config
->start_type
= SVCCTL_DISABLED
;
754 else if ( strequal( name
, "WINS" ) && ( !lp_we_are_a_wins_server() ))
755 config
->start_type
= SVCCTL_DISABLED
;
757 config
->start_type
= SVCCTL_DEMAND_START
;
762 /********************************************************************
763 _svcctl_QueryServiceConfigW
764 ********************************************************************/
766 WERROR
_svcctl_QueryServiceConfigW(struct pipes_struct
*p
,
767 struct svcctl_QueryServiceConfigW
*r
)
769 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
770 struct auth_session_info
*session_info
=
771 dcesrv_call_session_info(dce_call
);
772 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
773 uint32_t buffer_size
;
776 /* perform access checks */
778 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
779 return WERR_INVALID_HANDLE
;
781 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
782 return WERR_ACCESS_DENIED
;
784 /* we have to set the outgoing buffer size to the same as the
785 incoming buffer size (even in the case of failure */
787 *r
->out
.needed
= r
->in
.offered
;
789 wresult
= fill_svc_config(p
->mem_ctx
,
794 if ( !W_ERROR_IS_OK(wresult
) )
797 buffer_size
= ndr_size_QUERY_SERVICE_CONFIG(r
->out
.query
, 0);
798 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
800 if (buffer_size
> r
->in
.offered
) {
801 ZERO_STRUCTP(r
->out
.query
);
802 return WERR_INSUFFICIENT_BUFFER
;
808 /********************************************************************
809 _svcctl_QueryServiceConfig2W
810 ********************************************************************/
812 WERROR
_svcctl_QueryServiceConfig2W(struct pipes_struct
*p
,
813 struct svcctl_QueryServiceConfig2W
*r
)
815 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
816 struct auth_session_info
*session_info
=
817 dcesrv_call_session_info(dce_call
);
818 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
819 uint32_t buffer_size
;
820 DATA_BLOB blob
= data_blob_null
;
822 /* perform access checks */
824 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
825 return WERR_INVALID_HANDLE
;
827 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
828 return WERR_ACCESS_DENIED
;
830 /* we have to set the outgoing buffer size to the same as the
831 incoming buffer size (even in the case of failure */
832 *r
->out
.needed
= r
->in
.offered
;
834 switch ( r
->in
.info_level
) {
835 case SERVICE_CONFIG_DESCRIPTION
:
837 struct SERVICE_DESCRIPTION desc_buf
;
838 const char *description
;
839 enum ndr_err_code ndr_err
;
841 description
= svcctl_lookup_description(p
->mem_ctx
,
846 desc_buf
.description
= description
;
848 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &desc_buf
,
849 (ndr_push_flags_fn_t
)ndr_push_SERVICE_DESCRIPTION
);
850 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
851 return WERR_INVALID_PARAMETER
;
857 case SERVICE_CONFIG_FAILURE_ACTIONS
:
859 struct SERVICE_FAILURE_ACTIONSW actions
;
860 enum ndr_err_code ndr_err
;
862 /* nothing to say...just service the request */
864 ZERO_STRUCT( actions
);
866 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &actions
,
867 (ndr_push_flags_fn_t
)ndr_push_SERVICE_FAILURE_ACTIONSW
);
868 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
869 return WERR_INVALID_PARAMETER
;
877 return WERR_INVALID_LEVEL
;
880 buffer_size
= blob
.length
;
881 buffer_size
+= buffer_size
% 4;
882 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
884 if (buffer_size
> r
->in
.offered
)
885 return WERR_INSUFFICIENT_BUFFER
;
887 memcpy(r
->out
.buffer
, blob
.data
, blob
.length
);
892 /********************************************************************
893 _svcctl_LockServiceDatabase
894 ********************************************************************/
896 WERROR
_svcctl_LockServiceDatabase(struct pipes_struct
*p
,
897 struct svcctl_LockServiceDatabase
*r
)
899 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
901 /* perform access checks */
903 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
904 return WERR_INVALID_HANDLE
;
906 if ( !(info
->access_granted
& SC_RIGHT_MGR_LOCK
) )
907 return WERR_ACCESS_DENIED
;
909 /* Just open a handle. Doesn't actually lock anything */
911 return create_open_service_handle( p
, r
->out
.lock
, SVC_HANDLE_IS_DBLOCK
, NULL
, 0 );
914 /********************************************************************
915 _svcctl_UnlockServiceDatabase
916 ********************************************************************/
918 WERROR
_svcctl_UnlockServiceDatabase(struct pipes_struct
*p
,
919 struct svcctl_UnlockServiceDatabase
*r
)
921 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.lock
);
924 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_DBLOCK
) )
925 return WERR_INVALID_HANDLE
;
927 return close_policy_hnd( p
, r
->out
.lock
) ? WERR_OK
: WERR_INVALID_HANDLE
;
930 /********************************************************************
931 _svcctl_QueryServiceObjectSecurity
932 ********************************************************************/
934 WERROR
_svcctl_QueryServiceObjectSecurity(struct pipes_struct
*p
,
935 struct svcctl_QueryServiceObjectSecurity
*r
)
937 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
938 struct security_descriptor
*sec_desc
;
940 uint8_t *buffer
= NULL
;
945 /* only support the SCM and individual services */
947 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
948 return WERR_INVALID_HANDLE
;
950 /* check access reights (according to MSDN) */
952 if ( !(info
->access_granted
& SEC_STD_READ_CONTROL
) )
953 return WERR_ACCESS_DENIED
;
955 /* TODO: handle something besides SECINFO_DACL */
957 if ( (r
->in
.security_flags
& SECINFO_DACL
) != SECINFO_DACL
)
958 return WERR_INVALID_PARAMETER
;
960 /* Lookup the security descriptor and marshall it up for a reply */
961 err
= svcctl_get_secdesc(p
->msg_ctx
,
962 get_session_info_system(),
966 if (W_ERROR_EQUAL(err
, WERR_FILE_NOT_FOUND
)) {
967 DBG_NOTICE("service %s does not exist\n", info
->name
);
968 return WERR_SERVICE_DOES_NOT_EXIST
;
970 if (!W_ERROR_IS_OK(err
)) {
971 DBG_NOTICE("Failed to get a valid secdesc for %s: %s\n",
972 info
->name
, win_errstr(err
));
976 *r
->out
.needed
= ndr_size_security_descriptor(sec_desc
, 0);
978 if ( *r
->out
.needed
> r
->in
.offered
) {
979 return WERR_INSUFFICIENT_BUFFER
;
982 status
= marshall_sec_desc(p
->mem_ctx
, sec_desc
, &buffer
, &len
);
983 if (!NT_STATUS_IS_OK(status
)) {
984 return ntstatus_to_werror(status
);
987 *r
->out
.needed
= len
;
988 memcpy(r
->out
.buffer
, buffer
, len
);
993 /********************************************************************
994 _svcctl_SetServiceObjectSecurity
995 ********************************************************************/
997 WERROR
_svcctl_SetServiceObjectSecurity(struct pipes_struct
*p
,
998 struct svcctl_SetServiceObjectSecurity
*r
)
1000 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
1001 struct auth_session_info
*session_info
=
1002 dcesrv_call_session_info(dce_call
);
1003 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
1004 struct security_descriptor
*sec_desc
= NULL
;
1005 uint32_t required_access
;
1008 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
1009 return WERR_INVALID_HANDLE
;
1011 /* can't set the security de4scriptor on the ServiceControlManager */
1013 if ( info
->type
== SVC_HANDLE_IS_SCM
)
1014 return WERR_ACCESS_DENIED
;
1016 /* check the access on the open handle */
1018 switch ( r
->in
.security_flags
) {
1020 required_access
= SEC_STD_WRITE_DAC
;
1025 required_access
= SEC_STD_WRITE_OWNER
;
1029 return WERR_INVALID_PARAMETER
;
1031 return WERR_INVALID_PARAMETER
;
1034 if ( !(info
->access_granted
& required_access
) )
1035 return WERR_ACCESS_DENIED
;
1037 /* read the security descfriptor */
1039 status
= unmarshall_sec_desc(p
->mem_ctx
,
1043 if (!NT_STATUS_IS_OK(status
)) {
1044 return ntstatus_to_werror(status
);
1047 /* store the new SD */
1049 if (!svcctl_set_secdesc(p
->msg_ctx
, session_info
, info
->name
, sec_desc
))
1050 return WERR_ACCESS_DENIED
;
1056 WERROR
_svcctl_DeleteService(struct pipes_struct
*p
,
1057 struct svcctl_DeleteService
*r
)
1059 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1060 return WERR_NOT_SUPPORTED
;
1063 WERROR
_svcctl_SetServiceStatus(struct pipes_struct
*p
,
1064 struct svcctl_SetServiceStatus
*r
)
1066 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1067 return WERR_NOT_SUPPORTED
;
1070 WERROR
_svcctl_NotifyBootConfigStatus(struct pipes_struct
*p
,
1071 struct svcctl_NotifyBootConfigStatus
*r
)
1073 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1074 return WERR_NOT_SUPPORTED
;
1077 WERROR
_svcctl_SCSetServiceBitsW(struct pipes_struct
*p
,
1078 struct svcctl_SCSetServiceBitsW
*r
)
1080 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1081 return WERR_NOT_SUPPORTED
;
1084 WERROR
_svcctl_ChangeServiceConfigW(struct pipes_struct
*p
,
1085 struct svcctl_ChangeServiceConfigW
*r
)
1087 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1088 return WERR_NOT_SUPPORTED
;
1091 WERROR
_svcctl_CreateServiceW(struct pipes_struct
*p
,
1092 struct svcctl_CreateServiceW
*r
)
1094 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1095 return WERR_NOT_SUPPORTED
;
1098 WERROR
_svcctl_QueryServiceLockStatusW(struct pipes_struct
*p
,
1099 struct svcctl_QueryServiceLockStatusW
*r
)
1101 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1102 return WERR_NOT_SUPPORTED
;
1105 WERROR
_svcctl_GetServiceKeyNameW(struct pipes_struct
*p
,
1106 struct svcctl_GetServiceKeyNameW
*r
)
1108 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1109 return WERR_NOT_SUPPORTED
;
1112 WERROR
_svcctl_SCSetServiceBitsA(struct pipes_struct
*p
,
1113 struct svcctl_SCSetServiceBitsA
*r
)
1115 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1116 return WERR_NOT_SUPPORTED
;
1119 WERROR
_svcctl_ChangeServiceConfigA(struct pipes_struct
*p
,
1120 struct svcctl_ChangeServiceConfigA
*r
)
1122 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1123 return WERR_NOT_SUPPORTED
;
1126 WERROR
_svcctl_CreateServiceA(struct pipes_struct
*p
,
1127 struct svcctl_CreateServiceA
*r
)
1129 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1130 return WERR_NOT_SUPPORTED
;
1133 WERROR
_svcctl_EnumDependentServicesA(struct pipes_struct
*p
,
1134 struct svcctl_EnumDependentServicesA
*r
)
1136 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1137 return WERR_NOT_SUPPORTED
;
1140 WERROR
_svcctl_EnumServicesStatusA(struct pipes_struct
*p
,
1141 struct svcctl_EnumServicesStatusA
*r
)
1143 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1144 return WERR_NOT_SUPPORTED
;
1147 WERROR
_svcctl_OpenSCManagerA(struct pipes_struct
*p
,
1148 struct svcctl_OpenSCManagerA
*r
)
1150 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1151 return WERR_NOT_SUPPORTED
;
1154 WERROR
_svcctl_OpenServiceA(struct pipes_struct
*p
,
1155 struct svcctl_OpenServiceA
*r
)
1157 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1158 return WERR_NOT_SUPPORTED
;
1161 WERROR
_svcctl_QueryServiceConfigA(struct pipes_struct
*p
,
1162 struct svcctl_QueryServiceConfigA
*r
)
1164 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1165 return WERR_NOT_SUPPORTED
;
1168 WERROR
_svcctl_QueryServiceLockStatusA(struct pipes_struct
*p
,
1169 struct svcctl_QueryServiceLockStatusA
*r
)
1171 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1172 return WERR_NOT_SUPPORTED
;
1175 WERROR
_svcctl_StartServiceA(struct pipes_struct
*p
,
1176 struct svcctl_StartServiceA
*r
)
1178 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1179 return WERR_NOT_SUPPORTED
;
1182 WERROR
_svcctl_GetServiceDisplayNameA(struct pipes_struct
*p
,
1183 struct svcctl_GetServiceDisplayNameA
*r
)
1185 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1186 return WERR_NOT_SUPPORTED
;
1189 WERROR
_svcctl_GetServiceKeyNameA(struct pipes_struct
*p
,
1190 struct svcctl_GetServiceKeyNameA
*r
)
1192 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1193 return WERR_NOT_SUPPORTED
;
1196 WERROR
_svcctl_GetCurrentGroupeStateW(struct pipes_struct
*p
,
1197 struct svcctl_GetCurrentGroupeStateW
*r
)
1199 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1200 return WERR_NOT_SUPPORTED
;
1203 WERROR
_svcctl_EnumServiceGroupW(struct pipes_struct
*p
,
1204 struct svcctl_EnumServiceGroupW
*r
)
1206 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1207 return WERR_NOT_SUPPORTED
;
1210 WERROR
_svcctl_ChangeServiceConfig2A(struct pipes_struct
*p
,
1211 struct svcctl_ChangeServiceConfig2A
*r
)
1213 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1214 return WERR_NOT_SUPPORTED
;
1217 WERROR
_svcctl_ChangeServiceConfig2W(struct pipes_struct
*p
,
1218 struct svcctl_ChangeServiceConfig2W
*r
)
1220 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1221 return WERR_NOT_SUPPORTED
;
1224 WERROR
_svcctl_QueryServiceConfig2A(struct pipes_struct
*p
,
1225 struct svcctl_QueryServiceConfig2A
*r
)
1227 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1228 return WERR_NOT_SUPPORTED
;
1231 WERROR
_svcctl_EnumServicesStatusExA(struct pipes_struct
*p
,
1232 struct svcctl_EnumServicesStatusExA
*r
)
1234 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1235 return WERR_NOT_SUPPORTED
;
1238 WERROR
_svcctl_EnumServicesStatusExW(struct pipes_struct
*p
,
1239 struct svcctl_EnumServicesStatusExW
*r
)
1241 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1242 return WERR_NOT_SUPPORTED
;
1245 WERROR
_svcctl_SCSendTSMessage(struct pipes_struct
*p
,
1246 struct svcctl_SCSendTSMessage
*r
)
1248 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1249 return WERR_NOT_SUPPORTED
;
1252 /****************************************************************
1253 _svcctl_CreateServiceWOW64A
1254 ****************************************************************/
1256 WERROR
_svcctl_CreateServiceWOW64A(struct pipes_struct
*p
,
1257 struct svcctl_CreateServiceWOW64A
*r
)
1259 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1260 return WERR_NOT_SUPPORTED
;
1264 /****************************************************************
1265 _svcctl_CreateServiceWOW64W
1266 ****************************************************************/
1268 WERROR
_svcctl_CreateServiceWOW64W(struct pipes_struct
*p
,
1269 struct svcctl_CreateServiceWOW64W
*r
)
1271 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1272 return WERR_NOT_SUPPORTED
;
1276 /****************************************************************
1277 _Opnum46NotUsedOnWire
1278 ****************************************************************/
1280 void _Opnum46NotUsedOnWire(struct pipes_struct
*p
,
1281 struct Opnum46NotUsedOnWire
*r
)
1283 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1287 /****************************************************************
1288 _svcctl_NotifyServiceStatusChange
1289 ****************************************************************/
1291 WERROR
_svcctl_NotifyServiceStatusChange(struct pipes_struct
*p
,
1292 struct svcctl_NotifyServiceStatusChange
*r
)
1294 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1295 return WERR_NOT_SUPPORTED
;
1299 /****************************************************************
1300 _svcctl_GetNotifyResults
1301 ****************************************************************/
1303 WERROR
_svcctl_GetNotifyResults(struct pipes_struct
*p
,
1304 struct svcctl_GetNotifyResults
*r
)
1306 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1307 return WERR_NOT_SUPPORTED
;
1311 /****************************************************************
1312 _svcctl_CloseNotifyHandle
1313 ****************************************************************/
1315 WERROR
_svcctl_CloseNotifyHandle(struct pipes_struct
*p
,
1316 struct svcctl_CloseNotifyHandle
*r
)
1318 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1319 return WERR_NOT_SUPPORTED
;
1323 /****************************************************************
1324 _svcctl_ControlServiceExA
1325 ****************************************************************/
1327 WERROR
_svcctl_ControlServiceExA(struct pipes_struct
*p
,
1328 struct svcctl_ControlServiceExA
*r
)
1330 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1331 return WERR_NOT_SUPPORTED
;
1335 /****************************************************************
1336 _svcctl_ControlServiceExW
1337 ****************************************************************/
1339 WERROR
_svcctl_ControlServiceExW(struct pipes_struct
*p
,
1340 struct svcctl_ControlServiceExW
*r
)
1342 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1343 return WERR_NOT_SUPPORTED
;
1347 /****************************************************************
1348 _Opnum52NotUsedOnWire
1349 ****************************************************************/
1351 void _Opnum52NotUsedOnWire(struct pipes_struct
*p
,
1352 struct Opnum52NotUsedOnWire
*r
)
1354 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1358 /****************************************************************
1359 _Opnum53NotUsedOnWire
1360 ****************************************************************/
1362 void _Opnum53NotUsedOnWire(struct pipes_struct
*p
,
1363 struct Opnum53NotUsedOnWire
*r
)
1365 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1369 /****************************************************************
1370 _Opnum54NotUsedOnWire
1371 ****************************************************************/
1373 void _Opnum54NotUsedOnWire(struct pipes_struct
*p
,
1374 struct Opnum54NotUsedOnWire
*r
)
1376 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1380 /****************************************************************
1381 _Opnum55NotUsedOnWire
1382 ****************************************************************/
1384 void _Opnum55NotUsedOnWire(struct pipes_struct
*p
,
1385 struct Opnum55NotUsedOnWire
*r
)
1387 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1391 /****************************************************************
1392 _svcctl_QueryServiceConfigEx
1393 ****************************************************************/
1395 WERROR
_svcctl_QueryServiceConfigEx(struct pipes_struct
*p
,
1396 struct svcctl_QueryServiceConfigEx
*r
)
1398 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1399 return WERR_NOT_SUPPORTED
;
1403 /****************************************************************
1404 _Opnum57NotUsedOnWire
1405 ****************************************************************/
1407 void _Opnum57NotUsedOnWire(struct pipes_struct
*p
,
1408 struct Opnum57NotUsedOnWire
*r
)
1410 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1414 /****************************************************************
1415 _Opnum58NotUsedOnWire
1416 ****************************************************************/
1418 void _Opnum58NotUsedOnWire(struct pipes_struct
*p
,
1419 struct Opnum58NotUsedOnWire
*r
)
1421 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1425 /****************************************************************
1426 _Opnum59NotUsedOnWire
1427 ****************************************************************/
1429 void _Opnum59NotUsedOnWire(struct pipes_struct
*p
,
1430 struct Opnum59NotUsedOnWire
*r
)
1432 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1436 /****************************************************************
1437 _svcctl_CreateWowService
1438 ****************************************************************/
1440 WERROR
_svcctl_CreateWowService(struct pipes_struct
*p
,
1441 struct svcctl_CreateWowService
*r
)
1443 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1444 return WERR_NOT_SUPPORTED
;
1448 /****************************************************************
1449 _svcctl_OpenSCManager2
1450 ****************************************************************/
1452 WERROR
_svcctl_OpenSCManager2(struct pipes_struct
*p
,
1453 struct svcctl_OpenSCManager2
*r
)
1455 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1456 return WERR_NOT_SUPPORTED
;
1459 static NTSTATUS
svcctl__op_init_server(struct dcesrv_context
*dce_ctx
,
1460 const struct dcesrv_endpoint_server
*ep_server
);
1462 static NTSTATUS
svcctl__op_shutdown_server(struct dcesrv_context
*dce_ctx
,
1463 const struct dcesrv_endpoint_server
*ep_server
);
1465 #define DCESRV_INTERFACE_SVCCTL_INIT_SERVER \
1468 #define DCESRV_INTERFACE_SVCCTL_SHUTDOWN_SERVER \
1469 svcctl_shutdown_server
1471 static NTSTATUS
svcctl_init_server(struct dcesrv_context
*dce_ctx
,
1472 const struct dcesrv_endpoint_server
*ep_server
)
1474 struct messaging_context
*msg_ctx
= global_messaging_context();
1477 /* initialize the control hooks */
1478 init_service_op_table();
1480 ok
= svcctl_init_winreg(msg_ctx
);
1482 return NT_STATUS_UNSUCCESSFUL
;
1485 return svcctl__op_init_server(dce_ctx
, ep_server
);
1488 static NTSTATUS
svcctl_shutdown_server(struct dcesrv_context
*dce_ctx
,
1489 const struct dcesrv_endpoint_server
*ep_server
)
1491 shutdown_service_op_table();
1493 return svcctl__op_shutdown_server(dce_ctx
, ep_server
);
1496 /* include the generated boilerplate */
1497 #include "librpc/gen_ndr/ndr_svcctl_scompat.c"