s3-services: move services.h closer to services implementation.
[kai/samba.git] / source3 / rpc_server / srv_svcctl_nt.c
index 8ed308ad6bdef6456dc691e868b8317341aca2cf..86e329e2739bc83d27914d9c2fc199b13a325d69 100644 (file)
@@ -23,6 +23,9 @@
  */
 
 #include "includes.h"
+#include "../librpc/gen_ndr/srv_svcctl.h"
+#include "services/services.h"
+#include "registry.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -118,7 +121,7 @@ static struct service_control_op* find_service_by_name( const char *name )
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
+static NTSTATUS svcctl_access_check( struct security_descriptor *sec_desc, NT_USER_TOKEN *token,
                                      uint32 access_desired, uint32 *access_granted )
 {
        if ( geteuid() == sec_initial_uid() ) {
@@ -132,12 +135,12 @@ static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
 /********************************************************************
 ********************************************************************/
 
-static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
+static struct security_descriptor* construct_scm_sd( TALLOC_CTX *ctx )
 {
-       SEC_ACE ace[2];
+       struct security_ace ace[2];
        size_t i = 0;
-       SEC_DESC *sd;
-       SEC_ACL *theacl;
+       struct security_descriptor *sd;
+       struct security_acl *theacl;
        size_t sd_size;
 
        /* basic access for Everyone */
@@ -252,7 +255,7 @@ done:
 WERROR _svcctl_OpenSCManagerW(pipes_struct *p,
                              struct svcctl_OpenSCManagerW *r)
 {
-       SEC_DESC *sec_desc;
+       struct security_descriptor *sec_desc;
        uint32 access_granted = 0;
        NTSTATUS status;
 
@@ -277,7 +280,7 @@ WERROR _svcctl_OpenSCManagerW(pipes_struct *p,
 WERROR _svcctl_OpenServiceW(pipes_struct *p,
                            struct svcctl_OpenServiceW *r)
 {
-       SEC_DESC *sec_desc;
+       struct security_descriptor *sec_desc;
        uint32 access_granted = 0;
        NTSTATUS status;
        const char *service = NULL;
@@ -439,7 +442,7 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
        }
 
         for ( i=0; i<num_services; i++ ) {
-               buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], NULL, 0);
+               buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], 0);
        }
 
        buffer_size += buffer_size % 4;
@@ -454,7 +457,7 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
                enum ndr_err_code ndr_err;
                struct ndr_push *ndr;
 
-               ndr = ndr_push_init_ctx(p->mem_ctx, NULL);
+               ndr = ndr_push_init_ctx(p->mem_ctx);
                if (ndr == NULL) {
                        return WERR_INVALID_PARAM;
                }
@@ -464,14 +467,15 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err));
                }
-
                blob = ndr_push_blob(ndr);
-               memcpy(r->out.service, blob.data, r->in.offered);
+               memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered));
        }
 
        *r->out.needed                  = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
        *r->out.services_returned       = (uint32)num_services;
-       *r->out.resume_handle           = 0x0;
+       if (r->out.resume_handle) {
+               *r->out.resume_handle   = 0;
+       }
 
        return result;
 }
@@ -525,7 +529,7 @@ WERROR _svcctl_ControlService(pipes_struct *p,
                return info->ops->service_status( info->name,
                                                  r->out.service_status );
        default:
-               return WERR_ACCESS_DENIED;
+               return WERR_INVALID_PARAM;
        }
 }
 
@@ -546,6 +550,15 @@ WERROR _svcctl_EnumDependentServicesW(pipes_struct *p,
        if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
                return WERR_ACCESS_DENIED;
 
+       switch (r->in.state) {
+       case SERVICE_STATE_ACTIVE:
+       case SERVICE_STATE_INACTIVE:
+       case SERVICE_STATE_ALL:
+               break;
+       default:
+               return WERR_INVALID_PARAM;
+       }
+
        /* we have to set the outgoing buffer size to the same as the
           incoming buffer size (even in the case of failure */
        /* this is done in the autogenerated server already - gd */
@@ -592,8 +605,7 @@ WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p,
                        svc_stat_proc.process_id     = sys_getpid();
                        svc_stat_proc.service_flags  = 0x0;
 
-                       ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL,
-                                                      &svc_stat_proc,
+                       ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &svc_stat_proc,
                                                       (ndr_push_flags_fn_t)ndr_push_SERVICE_STATUS_PROCESS);
                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                                return WERR_INVALID_PARAM;
@@ -626,8 +638,8 @@ static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name,
                               struct QUERY_SERVICE_CONFIG *config,
                               NT_USER_TOKEN *token )
 {
-       REGVAL_CTR *values;
-       REGISTRY_VALUE *val;
+       struct regval_ctr *values;
+       struct regval_blob *val;
 
        /* retrieve the registry values for this service */
 
@@ -702,7 +714,7 @@ WERROR _svcctl_QueryServiceConfigW(pipes_struct *p,
        if ( !W_ERROR_IS_OK(wresult) )
                return wresult;
 
-       buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, NULL, 0);
+       buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, 0);
        *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
         if (buffer_size > r->in.offered ) {
@@ -748,14 +760,13 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p,
 
                        desc_buf.description = description;
 
-                       ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL,
-                                                      &desc_buf,
+                       ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &desc_buf,
                                                       (ndr_push_flags_fn_t)ndr_push_SERVICE_DESCRIPTION);
                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                                return WERR_INVALID_PARAM;
                        }
 
-                       buffer_size = ndr_size_SERVICE_DESCRIPTION(&desc_buf, NULL, 0);
+                       buffer_size = ndr_size_SERVICE_DESCRIPTION(&desc_buf, 0);
                        r->out.buffer = blob.data;
 
                        break;
@@ -771,14 +782,13 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p,
 
                        ZERO_STRUCT( actions );
 
-                       ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL,
-                                                      &actions,
+                       ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &actions,
                                                       (ndr_push_flags_fn_t)ndr_push_SERVICE_FAILURE_ACTIONS);
                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                                return WERR_INVALID_PARAM;
                        }
 
-                       buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS(&actions, NULL, 0);
+                       buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS(&actions, 0);
                        r->out.buffer = blob.data;
 
                        break;
@@ -844,7 +854,7 @@ WERROR _svcctl_QueryServiceObjectSecurity(pipes_struct *p,
                                          struct svcctl_QueryServiceObjectSecurity *r)
 {
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
-       SEC_DESC *sec_desc;
+       struct security_descriptor *sec_desc;
        NTSTATUS status;
        uint8_t *buffer = NULL;
        size_t len = 0;
@@ -870,10 +880,9 @@ WERROR _svcctl_QueryServiceObjectSecurity(pipes_struct *p,
        if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) )
                 return WERR_NOMEM;
 
-       *r->out.needed = ndr_size_security_descriptor( sec_desc, NULL, 0 );
+       *r->out.needed = ndr_size_security_descriptor(sec_desc, 0);
 
        if ( *r->out.needed > r->in.offered) {
-               ZERO_STRUCTP( &r->out.buffer );
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -896,7 +905,7 @@ WERROR _svcctl_SetServiceObjectSecurity(pipes_struct *p,
                                        struct svcctl_SetServiceObjectSecurity *r)
 {
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
-       SEC_DESC *sec_desc = NULL;
+       struct security_descriptor *sec_desc = NULL;
        uint32 required_access;
        NTSTATUS status;