r23801: The FSF has moved around a lot. This fixes their Mass Ave address.
[jra/samba/.git] / source3 / rpc_server / srv_svcctl.c
index d52816df800f291231017a7b3822be8e64b4de62..cc8de13562bea5f5d49d35a90b54b1f13b083c66 100644 (file)
@@ -1,15 +1,11 @@
-
 /* 
- *  Unix SMB/Netbios implementation.
- *  Version 1.9.
+ *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
- *  Copyright (C) Andrew Tridgell              1992-1997,
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- *  Copyright (C) Paul Ashton                       1997.
+ *  Copyright (C) Gerald Carter                   2005 - 2007
  *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation; either version 3 of the License, or
  *  (at your option) any later version.
  *  
  *  This program is distributed in the hope that it will be useful,
  *  GNU General Public License for more details.
  *  
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-
 #include "includes.h"
-#include "nterr.h"
 
-extern int DEBUGLEVEL;
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+static BOOL proxy_svcctl_call(pipes_struct *p, uint8 opnum)
+{
+       struct api_struct *fns;
+       int n_fns;
+
+       svcctl_get_pipe_fns(&fns, &n_fns);
+
+       if (opnum >= n_fns)
+               return False;
+
+       if (fns[opnum].opnum != opnum) {
+               smb_panic("SVCCTL function table not sorted\n");
+       }
+
+       return fns[opnum].fn(p);
+}
 
 
 /*******************************************************************
- svc_reply_unknown_1
  ********************************************************************/
-static void svc_reply_close(SVC_Q_CLOSE *q_r,
-                               prs_struct *rdata)
+
+static BOOL api_svcctl_close_service(pipes_struct *p)
 {
-       SVC_R_CLOSE r_u;
+       return proxy_svcctl_call( p, DCERPC_SVCCTL_CLOSESERVICEHANDLE );
+}
 
-       /* set up the REG unknown_1 response */
-       bzero(r_u.pol.data, POL_HND_SIZE);
+/*******************************************************************
+ ********************************************************************/
 
-       /* close the policy handle */
-       if (close_lsa_policy_hnd(&(q_r->pol)))
-       {
-               r_u.status = 0;
-       }
-       else
-       {
-               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
-       }
+static BOOL api_svcctl_open_scmanager(pipes_struct *p)
+{
+       SVCCTL_Q_OPEN_SCMANAGER q_u;
+       SVCCTL_R_OPEN_SCMANAGER r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_open_scmanager("", &q_u, data, 0))
+               return False;
 
-       DEBUG(5,("svc_unknown_1: %d\n", __LINE__));
+       r_u.status = _svcctl_open_scmanager(p, &q_u, &r_u);
 
-       /* store the response in the SMB stream */
-       svc_io_r_close("", &r_u, rdata, 0);
+       if(!svcctl_io_r_open_scmanager("", &r_u, rdata, 0))
+               return False;
 
-       DEBUG(5,("svc_unknown_1: %d\n", __LINE__));
+       return True;
 }
 
 /*******************************************************************
- api_svc_close
  ********************************************************************/
-static void api_svc_close( uint16 vuid, prs_struct *data,
-                                    prs_struct *rdata )
+
+static BOOL api_svcctl_open_service(pipes_struct *p)
 {
-       SVC_Q_CLOSE q_r;
-       svc_io_q_close("", &q_r, data, 0);
-       svc_reply_close(&q_r, rdata);
-}
+       SVCCTL_Q_OPEN_SERVICE q_u;
+       SVCCTL_R_OPEN_SERVICE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
 
+       if(!svcctl_io_q_open_service("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_open_service(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_open_service("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
 
 /*******************************************************************
- svc_reply_open_service
  ********************************************************************/
-static void svc_reply_open_service(SVC_Q_OPEN_SERVICE *q_u,
-                               prs_struct *rdata)
+
+static BOOL api_svcctl_get_display_name(pipes_struct *p)
 {
-       uint32 status     = 0;
-       POLICY_HND pol;
-       SVC_R_OPEN_SERVICE r_u;
-       fstring name;
+       SVCCTL_Q_GET_DISPLAY_NAME q_u;
+       SVCCTL_R_GET_DISPLAY_NAME r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
 
-       DEBUG(5,("svc_open_service: %d\n", __LINE__));
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
 
-       if (status == 0x0 && find_lsa_policy_by_hnd(&q_u->scman_pol) == -1)
-       {
-               status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
-       }
+       if(!svcctl_io_q_get_display_name("", &q_u, data, 0))
+               return False;
 
-       if (status == 0x0 && !open_lsa_policy_hnd(&pol))
-       {
-               status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
-       }
+       r_u.status = _svcctl_get_display_name(p, &q_u, &r_u);
 
-       unistr2_to_ascii(name, &q_u->uni_svc_name, sizeof(name)-1);
+       if(!svcctl_io_r_get_display_name("", &r_u, rdata, 0))
+               return False;
 
-       if (status == 0x0)
-       {
-               DEBUG(5,("svc_open_service: %s\n", name));
-               /* lkcl XXXX do a check on the name, here */
-       }
+       return True;
+}
 
-       if (status == 0x0 && !set_lsa_policy_reg_name(&pol, name))
-       {
-               status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
-       }
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_query_status(pipes_struct *p)
+{
+       SVCCTL_Q_QUERY_STATUS q_u;
+       SVCCTL_R_QUERY_STATUS r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_query_status("", &q_u, data, 0))
+               return False;
 
-       make_svc_r_open_service(&r_u, &pol, status);
+       r_u.status = _svcctl_query_status(p, &q_u, &r_u);
 
-       /* store the response in the SMB stream */
-       svc_io_r_open_service("", &r_u, rdata, 0);
+       if(!svcctl_io_r_query_status("", &r_u, rdata, 0))
+               return False;
 
-       DEBUG(5,("svc_open_service: %d\n", __LINE__));
+       return True;
 }
 
 /*******************************************************************
- api_svc_open_service
  ********************************************************************/
-static void api_svc_open_service( uint16 vuid, prs_struct *data,
-                                    prs_struct *rdata )
+
+static BOOL api_svcctl_enum_services_status(pipes_struct *p)
 {
-       SVC_Q_OPEN_SERVICE q_u;
-       svc_io_q_open_service("", &q_u, data, 0);
-       svc_reply_open_service(&q_u, rdata);
-}
+       SVCCTL_Q_ENUM_SERVICES_STATUS q_u;
+       SVCCTL_R_ENUM_SERVICES_STATUS r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_enum_services_status("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_enum_services_status(p, &q_u, &r_u);
 
+       if(!svcctl_io_r_enum_services_status("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
 /*******************************************************************
- svc_reply_open_sc_man
  ********************************************************************/
-static void svc_reply_open_sc_man(SVC_Q_OPEN_SC_MAN *q_u,
-                               prs_struct *rdata)
+
+static BOOL api_svcctl_query_service_status_ex(pipes_struct *p)
 {
-       uint32 status     = 0;
-       POLICY_HND pol;
-       SVC_R_OPEN_SC_MAN r_u;
-       fstring name;
+       SVCCTL_Q_QUERY_SERVICE_STATUSEX q_u;
+       SVCCTL_R_QUERY_SERVICE_STATUSEX r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
 
-       DEBUG(5,("svc_open_sc_man: %d\n", __LINE__));
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
 
-       if (status == 0x0 && !open_lsa_policy_hnd(&pol))
-       {
-               status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
-       }
+       if(!svcctl_io_q_query_service_status_ex("", &q_u, data, 0))
+               return False;
 
-       unistr2_to_ascii(name, &q_u->uni_srv_name, sizeof(name)-1);
+       r_u.status = _svcctl_query_service_status_ex(p, &q_u, &r_u);
 
-       if (status == 0x0)
-       {
-               DEBUG(5,("svc_open_sc_man: %s\n", name));
-               /* lkcl XXXX do a check on the name, here */
-       }
+       if(!svcctl_io_r_query_service_status_ex("", &r_u, rdata, 0))
+               return False;
 
-       if (status == 0x0 && !set_lsa_policy_reg_name(&pol, name))
-       {
-               status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
-       }
+       return True;
+}
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_enum_dependent_services(pipes_struct *p)
+{
+       SVCCTL_Q_ENUM_DEPENDENT_SERVICES q_u;
+       SVCCTL_R_ENUM_DEPENDENT_SERVICES r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
 
-       make_svc_r_open_sc_man(&r_u, &pol, status);
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_enum_dependent_services("", &q_u, data, 0))
+               return False;
 
-       /* store the response in the SMB stream */
-       svc_io_r_open_sc_man("", &r_u, rdata, 0);
+       r_u.status = _svcctl_enum_dependent_services(p, &q_u, &r_u);
 
-       DEBUG(5,("svc_open_sc_man: %d\n", __LINE__));
+       if(!svcctl_io_r_enum_dependent_services("", &r_u, rdata, 0))
+               return False;
+
+       return True;
 }
 
 /*******************************************************************
- api_svc_open_sc_man
  ********************************************************************/
-static void api_svc_open_sc_man( uint16 vuid, prs_struct *data,
-                                    prs_struct *rdata )
+
+static BOOL api_svcctl_start_service(pipes_struct *p)
 {
-       SVC_Q_OPEN_SC_MAN q_u;
-       svc_io_q_open_sc_man("", &q_u, data, 0);
-       svc_reply_open_sc_man(&q_u, rdata);
+       SVCCTL_Q_START_SERVICE q_u;
+       SVCCTL_R_START_SERVICE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_start_service("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_start_service(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_start_service("", &r_u, rdata, 0))
+               return False;
+
+       return True;
 }
 
-static char *dummy_services[] =
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_control_service(pipes_struct *p)
 {
-       "imapd",
-       "popd",
-       "smbd",
-       "nmbd",
-       "httpd",
-       "inetd",
-       "syslogd",
-       NULL
-};
+       SVCCTL_Q_CONTROL_SERVICE q_u;
+       SVCCTL_R_CONTROL_SERVICE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_control_service("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_control_service(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_control_service("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
 
 /*******************************************************************
- svc_reply_enum_svcs_status
  ********************************************************************/
-static void svc_reply_enum_svcs_status(SVC_Q_ENUM_SVCS_STATUS *q_u,
-                               prs_struct *rdata)
+
+static BOOL api_svcctl_query_service_config(pipes_struct *p)
 {
-       uint32 dos_status = 0;
-       SVC_R_ENUM_SVCS_STATUS r_u;
-       ENUM_SRVC_STATUS *svcs = NULL;
-       int num_svcs = 0;
-       int buf_size = 0;
-       int i = get_enum_hnd(&q_u->resume_hnd);
-       uint32 resume_hnd = 0;
-       int max_buf_size = 0x10000;
+       SVCCTL_Q_QUERY_SERVICE_CONFIG q_u;
+       SVCCTL_R_QUERY_SERVICE_CONFIG r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
 
+       ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
 
-       DEBUG(5,("svc_enum_svcs_status: %d\n", __LINE__));
+       if(!svcctl_io_q_query_service_config("", &q_u, data, 0))
+               return False;
 
-       if (dos_status == 0x0 && find_lsa_policy_by_hnd(&q_u->pol) == -1)
-       {
-               dos_status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
-       }
+       r_u.status = _svcctl_query_service_config(p, &q_u, &r_u);
 
-       if (dos_status == 0x0)
-       {
-               DEBUG(5,("svc_enum_svcs_status:\n"));
-               while (dummy_services[i] != NULL)
-               {
-                       ENUM_SRVC_STATUS *svc = NULL;
-
-                       buf_size += strlen(dummy_services[i] + 1) * 2;
-                       buf_size += 9 * sizeof(uint32);
-
-                       DEBUG(10,("buf_size: %d q_u->buf_size: %d\n",
-                                  buf_size, q_u->buf_size));
-
-                       if (buf_size >= max_buf_size)
-                       {
-                               resume_hnd = i;
-                               break;
-                       }
-
-                       if (buf_size > q_u->buf_size)
-                       {
-                               dos_status = ERRmoredata;
-                               break;
-                       }
-
-                       num_svcs++;
-                       svcs = Realloc(svcs, num_svcs * sizeof(ENUM_SRVC_STATUS));
-                       if (svcs == NULL)
-                       {
-                               dos_status = ERRnomem;
-                               num_svcs = 0;
-                               break;
-                       }
-
-                       svc = &svcs[num_svcs-1];
-                       ZERO_STRUCTP(svc);
-
-                       make_unistr(&svc->uni_srvc_name, dummy_services[i]);
-                       make_unistr(&svc->uni_disp_name, dummy_services[i]);
-
-                       DEBUG(10,("show service: %s\n", dummy_services[i]));
-                       i++;
-               }
-       }
+       if(!svcctl_io_r_query_service_config("", &r_u, rdata, 0))
+               return False;
 
-       /*
-        * check for finished condition: no resume handle and last buffer fits
-        */
+       return True;
+}
 
-       if (resume_hnd == 0 && buf_size <= q_u->buf_size)
-       {
-               /* this indicates, along with resume_hnd of 0, an end. */
-               max_buf_size = 0;
-       }
+/*******************************************************************
+ ********************************************************************/
 
-       make_svc_r_enum_svcs_status(&r_u, svcs, max_buf_size, num_svcs, resume_hnd, dos_status);
+static BOOL api_svcctl_query_service_config2(pipes_struct *p)
+{
+       SVCCTL_Q_QUERY_SERVICE_CONFIG2 q_u;
+       SVCCTL_R_QUERY_SERVICE_CONFIG2 r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
 
-       /* store the response in the SMB stream */
-       svc_io_r_enum_svcs_status("", &r_u, rdata, 0);
+       if(!svcctl_io_q_query_service_config2("", &q_u, data, 0))
+               return False;
 
-       if (svcs != NULL)
-       {
-               free(svcs);
-       }
+       r_u.status = _svcctl_query_service_config2(p, &q_u, &r_u);
 
-       DEBUG(5,("svc_enum_svcs_status: %d\n", __LINE__));
+       if(!svcctl_io_r_query_service_config2("", &r_u, rdata, 0))
+               return False;
+
+       return True;
 }
 
 /*******************************************************************
- api_svc_enum_svcs_status
  ********************************************************************/
-static void api_svc_enum_svcs_status( uint16 vuid, prs_struct *data,
-                                    prs_struct *rdata )
+
+static BOOL api_svcctl_lock_service_db(pipes_struct *p)
 {
-       SVC_Q_ENUM_SVCS_STATUS q_u;
-       svc_io_q_enum_svcs_status("", &q_u, data, 0);
-       svc_reply_enum_svcs_status(&q_u, rdata);
+       SVCCTL_Q_LOCK_SERVICE_DB q_u;
+       SVCCTL_R_LOCK_SERVICE_DB r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_lock_service_db("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_lock_service_db(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_lock_service_db("", &r_u, rdata, 0))
+               return False;
+
+       return True;
 }
 
+
 /*******************************************************************
- svc_reply_query_disp_name
  ********************************************************************/
-static void svc_reply_query_disp_name(SVC_Q_QUERY_DISP_NAME *q_u,
-                               prs_struct *rdata)
+
+static BOOL api_svcctl_unlock_service_db(pipes_struct *p)
 {
-       SVC_R_QUERY_DISP_NAME r_u;
-       fstring svc_name;
-       uint32 status = 0;
+       SVCCTL_Q_UNLOCK_SERVICE_DB q_u;
+       SVCCTL_R_UNLOCK_SERVICE_DB r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
 
-       DEBUG(5,("svc_query_disp_name: %d\n", __LINE__));
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
 
-       if (find_lsa_policy_by_hnd(&q_u->scman_pol) == -1)
-       {
-               status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
-       }
+       if(!svcctl_io_q_unlock_service_db("", &q_u, data, 0))
+               return False;
 
-       /* for now display name = service name */
-       unistr2_to_ascii(svc_name, &q_u->uni_svc_name, sizeof(svc_name)-1);
-       make_svc_r_query_disp_name(&r_u, svc_name, status);
+       r_u.status = _svcctl_unlock_service_db(p, &q_u, &r_u);
 
-       /* store the response in the SMB stream */
-       svc_io_r_query_disp_name("", &r_u, rdata, 0);
+       if(!svcctl_io_r_unlock_service_db("", &r_u, rdata, 0))
+               return False;
 
-       DEBUG(5,("svc_query_disp_name: %d\n", __LINE__));
+       return True;
 }
 
 /*******************************************************************
- api_svc_query_disp_name
  ********************************************************************/
-static void api_svc_query_disp_name( uint16 vuid, prs_struct *data,
-                                    prs_struct *rdata )
+
+static BOOL api_svcctl_query_security_sec(pipes_struct *p)
 {
-       SVC_Q_QUERY_DISP_NAME q_u;
-       svc_io_q_query_disp_name("", &q_u, data, 0);
-       svc_reply_query_disp_name(&q_u, rdata);
+       SVCCTL_Q_QUERY_SERVICE_SEC q_u;
+       SVCCTL_R_QUERY_SERVICE_SEC r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_query_service_sec("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_query_service_sec(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_query_service_sec("", &r_u, rdata, 0))
+               return False;
+
+       return True;
 }
 
 /*******************************************************************
- array of \PIPE\svcctl operations
  ********************************************************************/
-static struct api_struct api_svc_cmds[] =
+
+static BOOL api_svcctl_set_security_sec(pipes_struct *p)
 {
-       { "SVC_CLOSE"           , SVC_CLOSE           , api_svc_close            },
-       { "SVC_OPEN_SC_MAN"     , SVC_OPEN_SC_MAN     , api_svc_open_sc_man      },
-       { "SVC_OPEN_SERVICE"    , SVC_OPEN_SERVICE    , api_svc_open_service     },
-       { "SVC_ENUM_SVCS_STATUS", SVC_ENUM_SVCS_STATUS, api_svc_enum_svcs_status },
-       { "SVC_QUERY_DISP_NAME" , SVC_QUERY_DISP_NAME , api_svc_query_disp_name  },
-       { NULL                  , 0                   , NULL                     }
-};
+       SVCCTL_Q_SET_SERVICE_SEC q_u;
+       SVCCTL_R_SET_SERVICE_SEC r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_set_service_sec("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_set_service_sec(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_set_service_sec("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
 
 /*******************************************************************
- receives a svcctl pipe and responds.
+ \PIPE\svcctl commands
  ********************************************************************/
-BOOL api_svcctl_rpc(pipes_struct *p, prs_struct *data)
+
+static struct api_struct api_svcctl_cmds[] =
+{
+      { "SVCCTL_CLOSE_SERVICE"              , SVCCTL_CLOSE_SERVICE              , api_svcctl_close_service },
+      { "SVCCTL_OPEN_SCMANAGER_W"           , SVCCTL_OPEN_SCMANAGER_W           , api_svcctl_open_scmanager },
+      { "SVCCTL_OPEN_SERVICE_W"             , SVCCTL_OPEN_SERVICE_W             , api_svcctl_open_service },
+      { "SVCCTL_GET_DISPLAY_NAME"           , SVCCTL_GET_DISPLAY_NAME           , api_svcctl_get_display_name },
+      { "SVCCTL_QUERY_STATUS"               , SVCCTL_QUERY_STATUS               , api_svcctl_query_status },
+      { "SVCCTL_QUERY_SERVICE_CONFIG_W"     , SVCCTL_QUERY_SERVICE_CONFIG_W     , api_svcctl_query_service_config },
+      { "SVCCTL_QUERY_SERVICE_CONFIG2_W"    , SVCCTL_QUERY_SERVICE_CONFIG2_W    , api_svcctl_query_service_config2 },
+      { "SVCCTL_ENUM_SERVICES_STATUS_W"     , SVCCTL_ENUM_SERVICES_STATUS_W     , api_svcctl_enum_services_status },
+      { "SVCCTL_ENUM_DEPENDENT_SERVICES_W"  , SVCCTL_ENUM_DEPENDENT_SERVICES_W  , api_svcctl_enum_dependent_services },
+      { "SVCCTL_START_SERVICE_W"            , SVCCTL_START_SERVICE_W            , api_svcctl_start_service },
+      { "SVCCTL_CONTROL_SERVICE"            , SVCCTL_CONTROL_SERVICE            , api_svcctl_control_service },
+      { "SVCCTL_QUERY_SERVICE_STATUSEX_W"   , SVCCTL_QUERY_SERVICE_STATUSEX_W   , api_svcctl_query_service_status_ex },
+      { "SVCCTL_LOCK_SERVICE_DB"            , SVCCTL_LOCK_SERVICE_DB            , api_svcctl_lock_service_db },
+      { "SVCCTL_UNLOCK_SERVICE_DB"          , SVCCTL_UNLOCK_SERVICE_DB          , api_svcctl_unlock_service_db },
+      { "SVCCTL_QUERY_SERVICE_SEC"          , SVCCTL_QUERY_SERVICE_SEC          , api_svcctl_query_security_sec },
+      { "SVCCTL_SET_SERVICE_SEC"            , SVCCTL_SET_SERVICE_SEC            , api_svcctl_set_security_sec }
+};
+
+
+void svcctl2_get_pipe_fns( struct api_struct **fns, int *n_fns )
 {
-       return api_rpcTNP(p, "api_svc_rpc", api_svc_cmds, data);
+        *fns = api_svcctl_cmds;
+       *n_fns = sizeof(api_svcctl_cmds) / sizeof(struct api_struct);
 }
 
+NTSTATUS rpc_svcctl2_init(void)
+{
+       return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION,
+                                         "svcctl", "ntsvcs", api_svcctl_cmds,
+                                         sizeof(api_svcctl_cmds) / sizeof(struct api_struct));
+}