svcctl: use offered/needed for buffer sizes as in spoolss.
[amitay/samba.git] / source3 / rpc_server / srv_svcctl_nt.c
index b90a189f7e3fcb14361af9caedcc2f9d0b7197a7..ddfe0df10b9f1ff2ee67776d2e054d6527299a5e 100644 (file)
@@ -32,8 +32,6 @@ struct service_control_op {
        SERVICE_CONTROL_OPS *ops;
 };
 
-#define SVCCTL_NUM_INTERNAL_SERVICES   4
-
 /* handle external services */
 extern SERVICE_CONTROL_OPS rcinit_svc_ops;
 
@@ -170,7 +168,7 @@ static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
  Find a registry key handle and return a SERVICE_INFO
  *****************************************************************/
 
-static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd)
+static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, struct policy_handle *hnd)
 {
        SERVICE_INFO *service_info = NULL;
 
@@ -185,7 +183,7 @@ static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd)
 /******************************************************************
  *****************************************************************/
 
-static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, uint32 type,
+static WERROR create_open_service_handle( pipes_struct *p, struct policy_handle *handle, uint32 type,
                                           const char *service, uint32 access_granted )
 {
        SERVICE_INFO *info = NULL;
@@ -446,7 +444,7 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
 
        buffer_size += buffer_size % 4;
 
-       if (buffer_size > r->in.buf_size ) {
+       if (buffer_size > r->in.offered) {
                num_services = 0;
                result = WERR_MORE_DATA;
        }
@@ -468,10 +466,12 @@ WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
                }
 
                blob = ndr_push_blob(ndr);
+               if (blob.length >= r->in.offered) {
+                       memcpy(r->out.service, blob.data, r->in.offered);
+               }
        }
 
-       r->out.service                  = blob.data;
-       *r->out.bytes_needed            = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+       *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;
 
@@ -552,7 +552,7 @@ WERROR _svcctl_EnumDependentServicesW(pipes_struct *p,
           incoming buffer size (even in the case of failure */
        /* this is done in the autogenerated server already - gd */
 
-       *r->out.bytes_needed = r->in.buf_size;
+       *r->out.needed = r->in.offered;
 
        /* no dependent services...basically a stub function */
        *r->out.services_returned = 0;
@@ -580,7 +580,7 @@ WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p,
 
        /* we have to set the outgoing buffer size to the same as the
           incoming buffer size (even in the case of failure) */
-       *r->out.bytes_needed = r->in.buf_size;
+       *r->out.needed = r->in.offered;
 
        switch ( r->in.info_level ) {
                case SVC_STATUS_PROCESS_INFO:
@@ -612,9 +612,9 @@ WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p,
 
 
         buffer_size += buffer_size % 4;
-       *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+       *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
-        if (buffer_size > r->in.buf_size ) {
+        if (buffer_size > r->in.offered ) {
                 return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -697,7 +697,7 @@ WERROR _svcctl_QueryServiceConfigW(pipes_struct *p,
        /* we have to set the outgoing buffer size to the same as the
           incoming buffer size (even in the case of failure */
 
-       *r->out.bytes_needed = r->in.buf_size;
+       *r->out.needed = r->in.offered;
 
        wresult = fill_svc_config( p->mem_ctx, info->name, r->out.query,
                                   p->server_info->ptok);
@@ -705,9 +705,9 @@ WERROR _svcctl_QueryServiceConfigW(pipes_struct *p,
                return wresult;
 
        buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, NULL, 0);
-       *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+       *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
-        if (buffer_size > r->in.buf_size ) {
+        if (buffer_size > r->in.offered ) {
                ZERO_STRUCTP(r->out.query);
                 return WERR_INSUFFICIENT_BUFFER;
        }
@@ -735,7 +735,7 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p,
 
        /* we have to set the outgoing buffer size to the same as the
           incoming buffer size (even in the case of failure */
-       *r->out.bytes_needed = r->in.buf_size;
+       *r->out.needed = r->in.offered;
 
        switch ( r->in.info_level ) {
        case SERVICE_CONFIG_DESCRIPTION:
@@ -792,9 +792,9 @@ WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p,
        }
 
        buffer_size += buffer_size % 4;
-       *r->out.bytes_needed = (buffer_size > r->in.buf_size) ? buffer_size : r->in.buf_size;
+       *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
-        if (buffer_size > r->in.buf_size )
+        if (buffer_size > r->in.offered)
                 return WERR_INSUFFICIENT_BUFFER;
 
        return WERR_OK;