drsuapi.idl: fix source_dsa spelling
[samba4-gss.git] / source3 / rpc_server / svcctl / srv_svcctl_nt.c
blob0bac31efac35f3c17d7c9f47ea47e6012b4c308c
1 /*
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/>.
25 #include "includes.h"
26 #include "system/passwd.h" /* uid_wrapper */
27 #include "ntdomain.h"
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"
32 #include "auth.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"
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_RPC_SRV
45 struct service_control_op {
46 const char *name;
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 );
79 int i;
81 if ( !(svcctl_ops = talloc_array( NULL, struct service_control_op, num_services+1)) ) {
82 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
83 return False;
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;
97 i++;
99 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
100 svcctl_ops[i].ops = &netlogon_svc_ops;
101 i++;
103 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
104 svcctl_ops[i].ops = &winreg_svc_ops;
105 i++;
107 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
108 svcctl_ops[i].ops = &wins_svc_ops;
109 i++;
111 /* NULL terminate the array */
113 svcctl_ops[i].name = NULL;
114 svcctl_ops[i].ops = NULL;
116 return True;
119 bool shutdown_service_op_table(void)
121 TALLOC_FREE(svcctl_ops);
123 return true;
126 /********************************************************************
127 ********************************************************************/
129 static struct service_control_op* find_service_by_name( const char *name )
131 int i;
133 for ( i=0; svcctl_ops[i].name; i++ ) {
134 if ( strequal( name, svcctl_ops[i].name ) )
135 return &svcctl_ops[i];
138 return NULL;
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 )
146 NTSTATUS status;
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)) {
151 return 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] = {};
164 size_t i = 0;
165 struct security_descriptor *sd;
166 struct security_acl *theacl;
167 size_t sd_size;
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)) )
183 return NULL;
185 if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
186 SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
187 theacl, &sd_size)) )
188 return NULL;
190 return sd;
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;
201 NTSTATUS status;
203 service_info = find_policy_by_hnd(p,
204 hnd,
205 DCESRV_HANDLE_ANY,
206 SERVICE_INFO,
207 &status);
208 if (!NT_STATUS_IS_OK(status)) {
209 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
210 return NULL;
213 return service_info;
216 /******************************************************************
217 *****************************************************************/
219 static WERROR create_open_service_handle(struct pipes_struct *p,
220 struct policy_handle *handle,
221 uint32_t type,
222 const char *service,
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;
236 switch ( type ) {
237 case SVC_HANDLE_IS_SCM:
238 info->type = SVC_HANDLE_IS_SCM;
239 break;
241 case SVC_HANDLE_IS_DBLOCK:
242 info->type = SVC_HANDLE_IS_DBLOCK;
243 break;
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;
252 goto done;
255 info->ops = s_op->ops;
257 if ( !(info->name = talloc_strdup( info, s_op->name )) ) {
258 result = WERR_NOT_ENOUGH_MEMORY;
259 goto done;
261 break;
263 default:
264 result = WERR_SERVICE_DOES_NOT_EXIST;
265 goto done;
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;
274 goto done;
277 done:
278 if ( !W_ERROR_IS_OK(result) )
279 TALLOC_FREE(info);
281 return 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;
296 NTSTATUS status;
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 /********************************************************************
313 _svcctl_OpenServiceW
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;
324 NTSTATUS status;
325 const char *service = NULL;
326 WERROR err;
328 service = r->in.ServiceName;
329 if (!service) {
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(),
345 service,
346 p->mem_ctx,
347 &sec_desc);
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));
355 return 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);
379 return WERR_OK;
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);
392 const char *service;
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,
404 p->msg_ctx,
405 session_info,
406 service);
407 if (!display_name) {
408 display_name = "";
411 *r->out.display_name = display_name;
412 *r->out.display_name_length = strlen(display_name);
414 return WERR_OK;
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;
448 int i;
449 struct ENUM_SERVICE_STATUSW *st;
450 const char *display_name;
452 /* just count */
453 while ( svcctl_ops[num_services].name )
454 num_services++;
456 if ( !(st = talloc_array( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) {
457 DEBUG(0,("enumerate_status: talloc() failed!\n"));
458 return -1;
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,
465 msg_ctx,
466 session_info,
467 svcctl_ops[i].name);
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 );
473 *status = st;
475 return num_services;
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;
489 int num_services;
490 int i = 0;
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,
506 p->msg_ctx,
507 session_info,
508 &services);
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) {
520 num_services = 0;
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);
530 if (ndr == NULL) {
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;
549 return result;
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 );
600 default:
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:
626 break;
627 default:
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;
640 return WERR_OK;
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;
670 DATA_BLOB blob;
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);
685 break;
688 default:
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;
700 return WERR_OK;
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,
709 const char *name,
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,
719 msg_ctx,
720 session_info,
721 name);
723 result = svcctl_get_string_value(mem_ctx,
724 msg_ctx,
725 session_info,
726 name,
727 "ObjectName");
728 if (result != NULL) {
729 config->startname = result;
732 result = svcctl_get_string_value(mem_ctx,
733 msg_ctx,
734 session_info,
735 name,
736 "ImagePath");
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
750 are not running */
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;
756 else
757 config->start_type = SVCCTL_DEMAND_START;
759 return WERR_OK;
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;
774 WERROR wresult;
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,
790 p->msg_ctx,
791 session_info,
792 info->name,
793 r->out.query);
794 if ( !W_ERROR_IS_OK(wresult) )
795 return 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;
805 return WERR_OK;
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,
842 p->msg_ctx,
843 session_info,
844 info->name);
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;
854 break;
856 break;
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;
872 break;
874 break;
876 default:
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);
889 return WERR_OK;
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;
939 NTSTATUS status;
940 uint8_t *buffer = NULL;
941 size_t len = 0;
942 WERROR err;
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(),
963 info->name,
964 p->mem_ctx,
965 &sec_desc);
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));
973 return 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);
990 return WERR_OK;
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;
1006 NTSTATUS status;
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 ) {
1019 case SECINFO_DACL:
1020 required_access = SEC_STD_WRITE_DAC;
1021 break;
1023 case SECINFO_OWNER:
1024 case SECINFO_GROUP:
1025 required_access = SEC_STD_WRITE_OWNER;
1026 break;
1028 case SECINFO_SACL:
1029 return WERR_INVALID_PARAMETER;
1030 default:
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,
1040 r->in.buffer,
1041 r->in.offered,
1042 &sec_desc);
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;
1052 return WERR_OK;
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 \
1466 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();
1475 bool ok;
1477 /* initialize the control hooks */
1478 init_service_op_table();
1480 ok = svcctl_init_winreg(msg_ctx);
1481 if (!ok) {
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"