summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h13
-rw-r--r--source3/include/rpc_svcctl.h11
-rw-r--r--source3/libsmb/smberr.c65
-rw-r--r--source3/rpc_client/cli_svcctl.c17
-rw-r--r--source3/rpc_parse/parse_misc.c1
-rw-r--r--source3/rpc_parse/parse_prs.c13
-rw-r--r--source3/rpc_parse/parse_svc.c243
-rw-r--r--source3/rpc_server/srv_svcctl.c114
-rw-r--r--source3/rpcclient/cmd_svcctl.c12
9 files changed, 394 insertions, 95 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index de2d6f476c..e8d232645a 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -487,6 +487,7 @@ void pwdb_set_must_change_time(char *p, int max_len, time_t t);
void pwdb_set_last_set_time(char *p, int max_len, time_t t);
void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl);
BOOL pwdb_gethexpwd(const char *p, char *pwd);
+BOOL pwdb_init_myworkgroup(void);
BOOL pwdb_initialise(BOOL is_server);
/*The following definitions come from lib/util_sid.c */
@@ -746,6 +747,7 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
/*The following definitions come from libsmb/smberr.c */
+char *smb_err_msg(uint8 class, uint32 num);
char *smb_errstr(char *inbuf);
/*The following definitions come from locking/locking.c */
@@ -1778,7 +1780,8 @@ BOOL do_svc_open_sc_man(struct cli_state *cli, uint16 fnum,
BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
POLICY_HND *hnd,
uint32 services_type, uint32 services_state,
- uint32 buf_size, uint32 *resume_hnd);
+ uint32 buf_size, uint32 *resume_hnd,
+ ENUM_SRVC_STATUS **svcs);
BOOL do_svc_close(struct cli_state *cli, uint16 fnum, POLICY_HND *hnd);
/*The following definitions come from rpc_client/cli_wkssvc.c */
@@ -2503,8 +2506,14 @@ void make_svc_r_open_sc_man(SVC_R_OPEN_SC_MAN *r_u, POLICY_HND *hnd,
void svc_io_r_open_sc_man(char *desc, SVC_R_OPEN_SC_MAN *r_u, prs_struct *ps, int depth);
void make_svc_q_enum_svcs_status(SVC_Q_ENUM_SVCS_STATUS *q_c, POLICY_HND *hnd,
uint32 service_type, uint32 service_state,
- uint32 buf_size, uint32 enum_hnd );
+ uint32 buf_size, uint32 resume_hnd );
void svc_io_q_enum_svcs_status(char *desc, SVC_Q_ENUM_SVCS_STATUS *q_u, prs_struct *ps, int depth);
+void make_svc_r_enum_svcs_status(SVC_R_ENUM_SVCS_STATUS *r_c,
+ ENUM_SRVC_STATUS *svcs, uint32 more_buf_size,
+ uint32 num_svcs, uint32 resume_hnd,
+ uint32 dos_status);
+void svc_io_r_enum_svcs_status(char *desc, SVC_R_ENUM_SVCS_STATUS *svc, prs_struct *ps, int depth);
+void svc_io_svc_status(char *desc, SVC_STATUS *svc, prs_struct *ps, int depth);
void make_svc_q_close(SVC_Q_CLOSE *q_c, POLICY_HND *hnd);
void svc_io_q_close(char *desc, SVC_Q_CLOSE *q_u, prs_struct *ps, int depth);
void svc_io_r_close(char *desc, SVC_R_CLOSE *r_u, prs_struct *ps, int depth);
diff --git a/source3/include/rpc_svcctl.h b/source3/include/rpc_svcctl.h
index 4241928218..451fdaa459 100644
--- a/source3/include/rpc_svcctl.h
+++ b/source3/include/rpc_svcctl.h
@@ -65,14 +65,14 @@ typedef struct svc_status_info
} SVC_STATUS;
-/* ENUM_SVC_STATUS */
+/* ENUM_SRVC_STATUS */
typedef struct enum_svc_status_info
{
UNISTR uni_srvc_name;
UNISTR uni_disp_name;
SVC_STATUS status;
-} ENUM_SVC_STATUS;
+} ENUM_SRVC_STATUS;
/* SVC_Q_ENUM_SVCS_STATUS */
typedef struct q_svc_enum_svcs_status_info
@@ -89,8 +89,11 @@ typedef struct q_svc_enum_svcs_status_info
typedef struct r_svc_enum_svcs_status_info
{
uint32 buf_size; /* service buffer size */
- ENUM_SVC_STATUS *svcs;
- uint32 status; /* return status */
+ ENUM_SRVC_STATUS *svcs;
+ uint32 more_buf_size;
+ uint32 num_svcs;
+ ENUM_HND resume_hnd; /* resume handle */
+ uint32 dos_status; /* return status, DOS error code (wow!) */
} SVC_R_ENUM_SVCS_STATUS;
diff --git a/source3/libsmb/smberr.c b/source3/libsmb/smberr.c
index c2d8884d73..4fd9165c69 100644
--- a/source3/libsmb/smberr.c
+++ b/source3/libsmb/smberr.c
@@ -147,35 +147,48 @@ struct
/****************************************************************************
return a SMB error string from a SMB buffer
****************************************************************************/
-char *smb_errstr(char *inbuf)
+char *smb_err_msg(uint8 class, uint32 num)
{
- static pstring ret;
- int class = CVAL(inbuf,smb_rcls);
- int num = SVAL(inbuf,smb_err);
- int i,j;
+ static pstring ret;
+ int i,j;
- for (i=0;err_classes[i].class;i++)
- if (err_classes[i].code == class)
- {
- if (err_classes[i].err_msgs)
- {
- err_code_struct *err = err_classes[i].err_msgs;
- for (j=0;err[j].name;j++)
- if (num == err[j].code)
+ for (i=0;err_classes[i].class;i++)
+ {
+ if (err_classes[i].code == class)
{
- if (DEBUGLEVEL > 0)
- slprintf(ret, sizeof(ret) - 1, "%s - %s (%s)",err_classes[i].class,
- err[j].name,err[j].message);
- else
- slprintf(ret, sizeof(ret) - 1, "%s - %s",err_classes[i].class,err[j].name);
- return ret;
+ err_code_struct *err = err_classes[i].err_msgs;
+ if (err != NULL)
+ {
+ for (j=0;err[j].name;j++)
+ {
+ if (num == err[j].code)
+ {
+ if (DEBUGLEVEL > 0)
+ {
+ slprintf(ret, sizeof(ret) - 1, "%s - %s (%s)",err_classes[i].class,
+ err[j].name,err[j].message);
+ }
+ else
+ {
+ slprintf(ret, sizeof(ret) - 1, "%s - %s",err_classes[i].class,err[j].name);
+ }
+ return ret;
+ }
+ }
+ }
+
}
- }
- slprintf(ret, sizeof(ret) - 1, "%s - %d",err_classes[i].class,num);
- return ret;
- }
-
- slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",class,num);
- return(ret);
+ slprintf(ret, sizeof(ret) - 1, "%s - %d",err_classes[i].class, num);
+ return ret;
+ }
+ slprintf(ret, sizeof(ret) - 1, "Error: Unknown error (%d,%d)",class,num);
+ return(ret);
+}
+/****************************************************************************
+return a SMB error string from a SMB buffer
+****************************************************************************/
+char *smb_errstr(char *inbuf)
+{
+ return smb_err_msg(CVAL(inbuf,smb_rcls), SVAL(inbuf,smb_err));
}
diff --git a/source3/rpc_client/cli_svcctl.c b/source3/rpc_client/cli_svcctl.c
index 90d74188da..3535c90391 100644
--- a/source3/rpc_client/cli_svcctl.c
+++ b/source3/rpc_client/cli_svcctl.c
@@ -97,7 +97,8 @@ do a SVC Enumerate Services
BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
POLICY_HND *hnd,
uint32 services_type, uint32 services_state,
- uint32 buf_size, uint32 *resume_hnd)
+ uint32 buf_size, uint32 *resume_hnd,
+ ENUM_SRVC_STATUS **svcs)
{
prs_struct rbuf;
prs_struct buf;
@@ -123,7 +124,6 @@ BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, fnum, SVC_ENUM_SVCS_STATUS, &buf, &rbuf))
{
-#if 0
SVC_R_ENUM_SVCS_STATUS r_o;
BOOL p;
@@ -132,22 +132,19 @@ BOOL do_svc_enum_svcs(struct cli_state *cli, uint16 fnum,
svc_io_r_enum_svcs_status("", &r_o, &rbuf, 0);
p = rbuf.offset != 0;
- if (p && r_o.status != 0)
+ if (p && r_o.dos_status != 0)
{
/* report error code */
- DEBUG(0,("SVC_ENUM_SVCS_STATUS: %s\n", get_nt_error_msg(r_o.status)));
- p = False;
+ DEBUG(0,("SVC_ENUM_SVCS_STATUS: %s\n", smb_err_msg(ERRDOS, r_o.dos_status)));
+ p = r_o.dos_status != ERRmoredata;
}
if (p)
{
- /* ok, at last: we're happy. return the policy handle */
- memcpy(hnd, r_o.pol.data, sizeof(hnd->data));
+ (*svcs) = r_o.svcs;
+ (*resume_hnd) = get_enum_hnd(&r_o.resume_hnd);
valid_pol = True;
}
-#else
- valid_pol = True;
-#endif
}
prs_mem_free(&rbuf);
diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c
index fdc67d0905..6b3fc9415e 100644
--- a/source3/rpc_parse/parse_misc.c
+++ b/source3/rpc_parse/parse_misc.c
@@ -343,7 +343,6 @@ void smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth)
prs_debug(ps, depth, desc, "smb_io_unistr");
depth++;
- prs_align(ps);
prs_unistr("unistr", ps, depth, uni);
}
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index 75432627ab..ef327f01a1 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -237,21 +237,22 @@ BOOL prs_unistr3(BOOL charmode, char *name, UNISTR3 *str, prs_struct *ps, int de
BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
{
char *q = mem_data(&(ps->data), ps->offset);
- int i = 0;
+ int i = -1;
uint8 *start = (uint8*)q;
if (q == NULL) return False;
- do
+ do
{
+ i++;
RW_SVAL(ps->io, q, str->buffer[i],0);
q += 2;
- i++;
-
- } while ((i < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
+ }
+ while ((i < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
(str->buffer[i] != 0));
- ps->offset += i*2;
+
+ ps->offset += (i+1)*2;
dump_data(5+depth, (char *)start, i * 2);
diff --git a/source3/rpc_parse/parse_svc.c b/source3/rpc_parse/parse_svc.c
index 2134d86f47..2ebab5aea5 100644
--- a/source3/rpc_parse/parse_svc.c
+++ b/source3/rpc_parse/parse_svc.c
@@ -135,6 +135,204 @@ void svc_io_q_enum_svcs_status(char *desc, SVC_Q_ENUM_SVCS_STATUS *q_u, prs_str
}
/*******************************************************************
+makes an SVC_R_ENUM_SVCS_STATUS structure.
+********************************************************************/
+void make_svc_r_enum_svcs_status(SVC_R_ENUM_SVCS_STATUS *r_c,
+ ENUM_SRVC_STATUS *svcs, uint32 more_buf_size,
+ uint32 num_svcs, uint32 resume_hnd,
+ uint32 dos_status)
+{
+ if (r_c == NULL) return;
+
+ DEBUG(5,("make_svc_r_enum_svcs_status\n"));
+
+ r_c->svcs = svcs;
+ r_c->more_buf_size = more_buf_size;
+ r_c->num_svcs = num_svcs;
+ make_enum_hnd(&r_c->resume_hnd, resume_hnd);
+ r_c->dos_status = dos_status;
+}
+
+/*******************************************************************
+reads or writes a SVC_R_ENUM_SVCS_STATUS structure.
+
+this is another wierd structure. WHY oh WHY can the microsoft teams
+not COMMUNICATE and get some CONSISTENCY TO THEIR DATA STRUCTURES!
+ARGH!
+
+********************************************************************/
+void svc_io_r_enum_svcs_status(char *desc, SVC_R_ENUM_SVCS_STATUS *svc, prs_struct *ps, int depth)
+{
+ int i;
+ if (svc == NULL) return;
+
+ prs_debug(ps, depth, desc, "svc_io_r_enum_svcs_status");
+ depth++;
+
+ prs_align(ps);
+
+ /*
+ * format is actually as laid out in SVC_R_ENUM_SVCS_STATUS.
+ * the reason for all the jumping about, which is horrible
+ * and can be avoided, is due to the use of offsets instead
+ * of pointers.
+ *
+ * if i ever find out that these offsets are in fact non-zero
+ * tokens just like pointer-tokens, i am going to go MAD.
+ */
+
+ if (ps->io)
+ {
+ /* reading */
+
+ uint32 buf_offset;
+ uint32 new_offset;
+
+ prs_uint32("buf_size", ps, depth, &(svc->buf_size));
+
+ buf_offset = ps->offset;
+ ps->offset = buf_offset + svc->buf_size;
+
+ prs_uint32("more_buf_size", ps, depth, &(svc->more_buf_size));
+ prs_uint32("num_svcs", ps, depth, &(svc->num_svcs));
+ smb_io_enum_hnd("resume_hnd", &(svc->resume_hnd), ps, depth);
+ prs_uint32("dos_status", ps, depth, &(svc->dos_status));
+
+ new_offset = ps->offset;
+ ps->offset = buf_offset;
+
+ svc->svcs = Realloc(NULL, svc->num_svcs * sizeof(ENUM_SRVC_STATUS));
+
+ if (svc->svcs == NULL)
+ {
+ DEBUG(0,("svc_io_r_enum_svcs_status: Realloc failed\n"));
+ ps->offset = 0x7fffffff;
+ return;
+ }
+
+ bzero(svc->svcs, svc->num_svcs * sizeof(ENUM_SRVC_STATUS));
+
+ for (i = 0; i < svc->num_svcs; i++)
+ {
+ fstring name;
+ uint32 old_offset;
+ uint32 srvc_offset;
+ uint32 disp_offset;
+
+ prs_uint32("srvc_offset", ps, depth, &srvc_offset);
+ prs_uint32("disp_offset", ps, depth, &disp_offset);
+ svc_io_svc_status("status", &svc->svcs[i].status, ps, depth);
+
+ old_offset = ps->offset;
+
+ ps->offset = buf_offset + srvc_offset;
+ slprintf(name, sizeof(name)-1, "srvc[%02d]", i);
+ smb_io_unistr(name, &svc->svcs[i].uni_srvc_name, ps, depth);
+
+ ps->offset = buf_offset + disp_offset;
+ slprintf(name, sizeof(name)-1, "disp[%02d]", i);
+ smb_io_unistr(name, &svc->svcs[i].uni_disp_name, ps, depth);
+
+ ps->offset = old_offset;
+ }
+
+ ps->offset = new_offset;
+ }
+ else
+ {
+ /* writing */
+
+ uint32 buf_offset;
+ uint32 old_buf_offset;
+ uint32 srvc_offset = 9 * sizeof(uint32) * svc->num_svcs;
+
+ prs_uint32_pre("buf_size", ps, depth, &svc->buf_size, &buf_offset);
+ old_buf_offset = ps->offset;
+
+ srvc_offset += old_buf_offset;
+
+ if (svc->svcs == NULL)
+ {
+ return;
+ }
+
+ for (i = 0; i < svc->num_svcs; i++)
+ {
+ fstring name;
+ uint32 old_offset;
+
+ /*
+ * store unicode string offset and unicode string
+ */
+
+ srvc_offset -= old_buf_offset;
+ prs_uint32("srvc_offset", ps, depth, &srvc_offset);
+ srvc_offset += old_buf_offset;
+
+ slprintf(name, sizeof(name)-1, "srvc[%02d]", i);
+
+ old_offset = ps->offset;
+ ps->offset = srvc_offset;
+ smb_io_unistr(name, &svc->svcs[i].uni_srvc_name, ps, depth);
+ srvc_offset = ps->offset;
+ ps->offset = old_offset;
+
+ /*
+ * store unicode string offset and unicode string
+ */
+
+ srvc_offset -= old_buf_offset;
+ prs_uint32("disp_offset", ps, depth, &srvc_offset);
+ srvc_offset += old_buf_offset;
+
+ slprintf(name, sizeof(name)-1, "disp[%02d]", i);
+
+ old_offset = ps->offset;
+ ps->offset = srvc_offset;
+ smb_io_unistr(name, &svc->svcs[i].uni_disp_name, ps, depth);
+ srvc_offset = ps->offset;
+ ps->offset = old_offset;
+
+ /*
+ * store status info
+ */
+
+ svc_io_svc_status("status", &svc->svcs[i].status, ps, depth);
+ }
+
+ prs_uint32_post("buf_size", ps, depth, &svc->buf_size, buf_offset, srvc_offset - buf_offset - sizeof(uint32));
+
+ ps->offset = srvc_offset;
+
+ prs_uint32("more_buf_size", ps, depth, &(svc->more_buf_size));
+ prs_uint32("num_svcs", ps, depth, &(svc->num_svcs));
+ smb_io_enum_hnd("resume_hnd", &(svc->resume_hnd), ps, depth);
+ prs_uint32("dos_status", ps, depth, &(svc->dos_status));
+ }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void svc_io_svc_status(char *desc, SVC_STATUS *svc, prs_struct *ps, int depth)
+{
+ if (svc == NULL) return;
+
+ prs_debug(ps, depth, desc, "svc_io_svc_status");
+ depth++;
+
+ prs_align(ps);
+
+ prs_uint32("svc_type", ps, depth, &(svc->svc_type));
+ prs_uint32("current_state", ps, depth, &(svc->current_state));
+ prs_uint32("controls_accepted", ps, depth, &(svc->controls_accepted));
+ prs_uint32("win32_exit_code", ps, depth, &(svc->win32_exit_code));
+ prs_uint32("svc_specific_exit_code", ps, depth, &(svc->svc_specific_exit_code));
+ prs_uint32("check_point", ps, depth, &(svc->check_point));
+ prs_uint32("wait_hint", ps, depth, &(svc->wait_hint));
+}
+
+/*******************************************************************
makes an SVC_Q_CLOSE structure.
********************************************************************/
void make_svc_q_close(SVC_Q_CLOSE *q_c, POLICY_HND *hnd)
@@ -180,48 +378,3 @@ void svc_io_r_close(char *desc, SVC_R_CLOSE *r_u, prs_struct *ps, int depth)
prs_uint32("status", ps, depth, &(r_u->status));
}
-#if 0
-/*******************************************************************
-reads or writes a SEC_DESC_BUF structure.
-********************************************************************/
-void sec_io_desc_buf(char *desc, SEC_DESC_BUF *sec, prs_struct *ps, int depth)
-{
- uint32 off_len;
- uint32 old_offset;
- uint32 size;
-
- if (sec == NULL) return;
-
- prs_debug(ps, depth, desc, "sec_io_desc_buf");
- depth++;
-
- prs_align(ps);
-
- prs_uint32_pre("max_len", ps, depth, &(sec->max_len), &off_max_len);
-
- old_offset = ps->offset;
-
- if (sec->len != 0 && ps->io)
- {
- /* reading */
- sec->sec = malloc(sizeof(*sec->sec));
- ZERO_STRUCTP(sec->sec);
-
- if (sec->sec == NULL)
- {
- DEBUG(0,("INVALID SEC_DESC\n"));
- ps->offset = 0xfffffffe;
- return;
- }
- }
-
- /* reading, length is non-zero; writing, descriptor is non-NULL */
- if ((sec->len != 0 || (!ps->io)) && sec->sec != NULL)
- {
- sec_io_desc("sec ", sec->sec, ps, depth);
- }
-
- size = ps->offset - old_offset;
- prs_uint32_post("max_len", ps, depth, &(sec->max_len), off_max_len, size == 0 ? sec->max_len : size);
-}
-#endif
diff --git a/source3/rpc_server/srv_svcctl.c b/source3/rpc_server/srv_svcctl.c
index be99063946..6cf9b8cd22 100644
--- a/source3/rpc_server/srv_svcctl.c
+++ b/source3/rpc_server/srv_svcctl.c
@@ -120,6 +120,119 @@ static void api_svc_open_sc_man( uint16 vuid, prs_struct *data,
svc_reply_open_sc_man(&q_u, rdata);
}
+static char *dummy_services[] =
+{
+ "imapd",
+ "popd",
+ "smbd",
+ "nmbd",
+ "httpd",
+ "inetd",
+ "syslogd",
+ NULL
+};
+
+/*******************************************************************
+ svc_reply_enum_svcs_status
+ ********************************************************************/
+static void svc_reply_enum_svcs_status(SVC_Q_ENUM_SVCS_STATUS *q_u,
+ prs_struct *rdata)
+{
+ 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 = 0x80;
+
+ ZERO_STRUCT(r_u);
+
+ DEBUG(5,("svc_enum_svcs_status: %d\n", __LINE__));
+
+ if (dos_status == 0x0 && find_lsa_policy_by_hnd(&q_u->pol) == -1)
+ {
+ dos_status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
+ }
+
+ 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 > q_u->buf_size)
+ {
+ if (buf_size >= max_buf_size)
+ {
+ resume_hnd = i;
+ }
+ 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++;
+ }
+ }
+
+ /*
+ * check for finished condition: no resume handle and last buffer fits
+ */
+
+ 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);
+
+ /* store the response in the SMB stream */
+ svc_io_r_enum_svcs_status("", &r_u, rdata, 0);
+
+ if (svcs != NULL)
+ {
+ free(svcs);
+ }
+
+ DEBUG(5,("svc_enum_svcs_status: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_svc_enum_svcs_status
+ ********************************************************************/
+static void api_svc_enum_svcs_status( uint16 vuid, prs_struct *data,
+ prs_struct *rdata )
+{
+ 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);
+}
+
/*******************************************************************
array of \PIPE\svcctl operations
********************************************************************/
@@ -127,6 +240,7 @@ static struct api_struct api_svc_cmds[] =
{
{ "SVC_CLOSE" , SVC_CLOSE , api_svc_close },
{ "SVC_OPEN_SC_MAN" , SVC_OPEN_SC_MAN , api_svc_open_sc_man },
+ { "SVC_ENUM_SVCS_STATUS", SVC_ENUM_SVCS_STATUS, api_svc_enum_svcs_status },
{ NULL, 0 , NULL }
};
diff --git a/source3/rpcclient/cmd_svcctl.c b/source3/rpcclient/cmd_svcctl.c
index 63f0d9651c..4f0978e17f 100644
--- a/source3/rpcclient/cmd_svcctl.c
+++ b/source3/rpcclient/cmd_svcctl.c
@@ -46,6 +46,7 @@ void cmd_svc_enum(struct client_info *info)
BOOL res1 = True;
int i;
uint32 resume_hnd = 0;
+ ENUM_SRVC_STATUS *svcs = NULL;
POLICY_HND sc_man_pol;
fstring full_keyname;
@@ -65,11 +66,20 @@ void cmd_svc_enum(struct client_info *info)
srv_name, NULL, 0x80000004,
&sc_man_pol) : False;
+ do
+ {
/* enumerate services */
res1 = res ? do_svc_enum_svcs(smb_cli, fnum,
&sc_man_pol,
0x00000030, 0x00000003,
- 0x00000200, &resume_hnd) : False;
+ 0x00000080, &resume_hnd, &svcs) : False;
+
+ } while (resume_hnd != 0);
+
+ if (svcs != NULL)
+ {
+ free(svcs);
+ }
#if 0
if (res1 && num_subkeys > 0)