r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
[vlendec/samba-autobuild/.git] / source3 / rpc_client / cli_srvsvc.c
index 5e4af69c6aa7676a0a6882aa80fcd84fdfe3a57f..7b4818b4b06363963afb10166a0943804e3d2176 100644 (file)
-
 /* 
- *  Unix SMB/Netbios implementation.
- *  Version 1.9.
- *  RPC Pipe client / server routines
- *  Copyright (C) Andrew Tridgell              1992-1997,
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- *  Copyright (C) Paul Ashton                       1997.
- *  
- *  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
- *  (at your option) any later version.
- *  
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  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.
- */
-
-
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
+   Unix SMB/CIFS implementation.
+   NT Domain Authentication SMB / MSRPC client
+   Copyright (C) Andrew Tridgell 1994-2000
+   Copyright (C) Tim Potter 2001
+   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
+   Copyright (C) Jeremy Allison  2005.
+   Copyright (C) Gerald (Jerry) Carter        2006.
+
+
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
 
 #include "includes.h"
 
-extern int DEBUGLEVEL;
+WERROR rpccli_srvsvc_net_srv_get_info(struct rpc_pipe_client *cli, 
+                                  TALLOC_CTX *mem_ctx,
+                                  uint32 switch_value, SRV_INFO_CTR *ctr)
+{
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_SRV_GET_INFO q;
+       SRV_R_NET_SRV_GET_INFO r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise input parameters */
+
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
+
+       init_srv_q_net_srv_get_info(&q, server, switch_value);
+       r.ctr = ctr;
+
+       /* Marshall data and send request */
+
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SRV_GET_INFO,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_srv_get_info,
+               srv_io_r_net_srv_get_info,
+               WERR_GENERAL_FAILURE);
 
-/****************************************************************************
-do a server net conn enum
-****************************************************************************/
-BOOL do_srv_net_srv_conn_enum(struct cli_state *cli, uint16 fnum,
-                       char *server_name, char *qual_name,
-                       uint32 switch_value, SRV_CONN_INFO_CTR *ctr,
-                       uint32 preferred_len,
-                       ENUM_HND *hnd)
+       result = r.status;
+       return result;
+}
+
+WERROR rpccli_srvsvc_net_share_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                uint32 info_level, SRV_SHARE_INFO_CTR *ctr,
+                                int preferred_len, ENUM_HND *hnd)
 {
-       prs_struct data; 
-       prs_struct rdata;
-       SRV_Q_NET_CONN_ENUM q_o;
-    BOOL valid_enum = False;
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_SHARE_ENUM q;
+       SRV_R_NET_SHARE_ENUM r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
+       int i;
 
-       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
-       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
-       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+       /* Initialise input parameters */
 
-       /* create and send a MSRPC command with api SRV_NETCONNENUM */
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       DEBUG(4,("SRV Net Server Connection Enum(%s, %s), level %d, enum:%8x\n",
-                               server_name, qual_name, switch_value, get_enum_hnd(hnd)));
-                               
-       ctr->switch_value = switch_value;
-       ctr->ptr_conn_ctr = 1;
-       ctr->conn.info0.num_entries_read = 0;
-       ctr->conn.info0.ptr_conn_info    = 1;
+       init_srv_q_net_share_enum(&q, server, info_level, preferred_len, hnd);
 
-       /* store the parameters */
-       make_srv_q_net_conn_enum(&q_o, server_name, qual_name,
-                                switch_value, ctr,
-                                preferred_len,
-                                hnd);
+       /* Marshall data and send request */
 
-       /* turn parameters into data stream */
-       srv_io_q_net_conn_enum("", &q_o, &data, 0);
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_ENUM_ALL,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_enum,
+               srv_io_r_net_share_enum,
+               WERR_GENERAL_FAILURE);
 
-       /* send the data on \PIPE\ */
-       if (rpc_api_pipe_req(cli, fnum, SRV_NETCONNENUM, &data, &rdata))
-       {
-               SRV_R_NET_CONN_ENUM r_o;
-               BOOL p;
+       result = r.status;
 
-               r_o.ctr = ctr;
+       if (!W_ERROR_IS_OK(result))
+               goto done;
 
-               srv_io_r_net_conn_enum("", &r_o, &rdata, 0);
-               p = rdata.offset != 0;
-               
-               if (p && r_o.status != 0)
-               {
-                       /* report error code */
-                       DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
-                       p = 0;
-               }
+       /* Oh yuck yuck yuck - we have to copy all the info out of the
+          SRV_SHARE_INFO_CTR in the SRV_R_NET_SHARE_ENUM as when we do a
+          prs_mem_free() it will all be invalidated.  The various share
+          info structures suck badly too.  This really is gross. */
 
-               if (p && r_o.ctr->switch_value != switch_value)
-               {
-                       /* different switch levels.  oops. */
-                       DEBUG(0,("SRV_R_NET_SRV_CONN_ENUM: info class %d does not match request %d\n",
-                               r_o.ctr->switch_value, switch_value));
-                       p = 0;
-               }
+       ZERO_STRUCTP(ctr);
+
+       if (!r.ctr.num_entries)
+               goto done;
 
-               if (p)
-               {
-                       /* ok, at last: we're happy. */
-                       valid_enum = True;
+       ctr->info_level = info_level;
+       ctr->num_entries = r.ctr.num_entries;
+
+       switch(info_level) {
+       case 1:
+               ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, ctr->num_entries);
+               if (ctr->share.info1 == NULL) {
+                       return WERR_NOMEM;
                }
-       }
+               
+               memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
 
-       prs_mem_free(&data   );
-       prs_mem_free(&rdata  );
-       
-       return valid_enum;
-}
+               for (i = 0; i < ctr->num_entries; i++) {
+                       SRV_SHARE_INFO_1 *info1 = &ctr->share.info1[i];
+                       char *s;
+                       
+                       /* Copy pointer crap */
 
-/****************************************************************************
-do a server net sess enum
-****************************************************************************/
-BOOL do_srv_net_srv_sess_enum(struct cli_state *cli, uint16 fnum,
-                       char *server_name, char *qual_name, char *user_name,
-                       uint32 switch_value, SRV_SESS_INFO_CTR *ctr,
-                       uint32 preferred_len,
-                       ENUM_HND *hnd)
-{
-       prs_struct data; 
-       prs_struct rdata;
-       SRV_Q_NET_SESS_ENUM q_o;
-    BOOL valid_enum = False;
+                       memcpy(&info1->info_1, &r.ctr.share.info1[i].info_1, 
+                              sizeof(SH_INFO_1));
+
+                       /* Duplicate strings */
 
-       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_netname);
+                       if (s)
+                               init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
+               
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_remark);
+                       if (s)
+                               init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
 
-       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
-       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+               }               
 
-       /* create and send a MSRPC command with api SRV_NETSESSENUM */
+               break;
+       case 2:
+               ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, ctr->num_entries);
+               if (ctr->share.info2 == NULL) {
+                       return WERR_NOMEM;
+               }
+               
+               memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
 
-       DEBUG(4,("SRV Net Session Enum (%s), level %d, enum:%8x\n",
-                               server_name, switch_value, get_enum_hnd(hnd)));
-                               
-       ctr->switch_value = switch_value;
-       ctr->ptr_sess_ctr = 1;
-       ctr->sess.info0.num_entries_read = 0;
-       ctr->sess.info0.ptr_sess_info    = 1;
+               for (i = 0; i < ctr->num_entries; i++) {
+                       SRV_SHARE_INFO_2 *info2 = &ctr->share.info2[i];
+                       char *s;
+                       
+                       /* Copy pointer crap */
 
-       /* store the parameters */
-       make_srv_q_net_sess_enum(&q_o, server_name, qual_name, user_name,
-                                switch_value, ctr,
-                                preferred_len,
-                                hnd);
+                       memcpy(&info2->info_2, &r.ctr.share.info2[i].info_2, 
+                              sizeof(SH_INFO_2));
 
-       /* turn parameters into data stream */
-       srv_io_q_net_sess_enum("", &q_o, &data, 0);
+                       /* Duplicate strings */
 
-       /* send the data on \PIPE\ */
-       if (rpc_api_pipe_req(cli, fnum, SRV_NETSESSENUM, &data, &rdata))
-       {
-               SRV_R_NET_SESS_ENUM r_o;
-               BOOL p;
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_netname);
+                       if (s)
+                               init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
 
-               r_o.ctr = ctr;
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_remark);
+                       if (s)
+                               init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
 
-               srv_io_r_net_sess_enum("", &r_o, &rdata, 0);
-               p = rdata.offset != 0;
-               
-               if (p && r_o.status != 0)
-               {
-                       /* report error code */
-                       DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
-                       p = 0;
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_path);
+                       if (s)
+                               init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
+
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_passwd);
+                       if (s)
+                               init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
                }
+               break;
+       /* adding info-level 502 here */
+       case 502:
+               ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, ctr->num_entries);
 
-               if (p && r_o.ctr->switch_value != switch_value)
-               {
-                       /* different switch levels.  oops. */
-                       DEBUG(0,("SRV_R_NET_SRV_SESS_ENUM: info class %d does not match request %d\n",
-                               r_o.ctr->switch_value, switch_value));
-                       p = 0;
+               if (ctr->share.info502 == NULL) {
+                       return WERR_NOMEM;
                }
+               
+               memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
 
-               if (p)
-               {
-                       /* ok, at last: we're happy. */
-                       valid_enum = True;
+               for (i = 0; i < ctr->num_entries; i++) {
+                       SRV_SHARE_INFO_502 *info502 = &ctr->share.info502[i];
+                       char *s;
+                       
+                       /* Copy pointer crap */
+                       memcpy(&info502->info_502, &r.ctr.share.info502[i].info_502, 
+                              sizeof(SH_INFO_502));
+
+                       /* Duplicate strings */
+
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_netname);
+                       if (s)
+                               init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
+
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_remark);
+                       if (s)
+                               init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
+
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_path);
+                       if (s)
+                               init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
+
+                       s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_passwd);
+                       if (s)
+                               init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
+               
+                       info502->info_502_str.sd = dup_sec_desc(mem_ctx, r.ctr.share.info502[i].info_502_str.sd);
                }
+               break;
        }
 
-       prs_mem_free(&data   );
-       prs_mem_free(&rdata  );
-       
-       return valid_enum;
+  done:
+
+       return result;
 }
 
-/****************************************************************************
-do a server net share enum
-****************************************************************************/
-BOOL do_srv_net_srv_share_enum(struct cli_state *cli, uint16 fnum,
-                       char *server_name, 
-                       uint32 switch_value, SRV_SHARE_INFO_CTR *ctr,
-                       uint32 preferred_len,
-                       ENUM_HND *hnd)
+WERROR rpccli_srvsvc_net_share_get_info(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    const char *sharename,
+                                    uint32 info_level,
+                                    SRV_SHARE_INFO *info)
 {
-       prs_struct data; 
-       prs_struct rdata;
-       SRV_Q_NET_SHARE_ENUM q_o;
-    BOOL valid_enum = False;
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_SHARE_GET_INFO q;
+       SRV_R_NET_SHARE_GET_INFO r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
-       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
-       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
-       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+       /* Initialise input parameters */
 
-       /* create and send a MSRPC command with api SRV_NETSHAREENUM */
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       DEBUG(4,("SRV Get Share Info (%s), level %d, enum:%8x\n",
-                               server_name, switch_value, get_enum_hnd(hnd)));
-                               
-       q_o.share_level = switch_value;
+       init_srv_q_net_share_get_info(&q, server, sharename, info_level);
 
-       ctr->switch_value = switch_value;
-       ctr->ptr_share_ctr = 1;
-       ctr->share.info1.num_entries_read = 0;
-       ctr->share.info1.ptr_share_info    = 1;
+       /* Marshall data and send request */
 
-       /* store the parameters */
-       make_srv_q_net_share_enum(&q_o, server_name, 
-                                switch_value, ctr,
-                                preferred_len,
-                                hnd);
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_GET_INFO,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_get_info,
+               srv_io_r_net_share_get_info,
+               WERR_GENERAL_FAILURE);
 
-       /* turn parameters into data stream */
-       srv_io_q_net_share_enum("", &q_o, &data, 0);
+       result = r.status;
 
-       /* send the data on \PIPE\ */
-       if (rpc_api_pipe_req(cli, fnum, SRV_NETSHAREENUM, &data, &rdata))
+       if (!W_ERROR_IS_OK(result))
+               goto done;
+
+       ZERO_STRUCTP(info);
+
+       info->switch_value = info_level;
+
+       switch(info_level) {
+       case 1:
        {
-               SRV_R_NET_SHARE_ENUM r_o;
-               BOOL p;
+               SRV_SHARE_INFO_1 *info1 = &info->share.info1;
+               SH_INFO_1_STR *info1_str = &info1->info_1_str;
+               
+               char *s;
+
+               info->share.info1 = r.info.share.info1;
+
+               /* Duplicate strings */
+
+               s = unistr2_tdup(mem_ctx, &info1_str->uni_netname);
+               if (s)
+                       init_unistr2(&info1_str->uni_netname,
+                                    s, UNI_STR_TERMINATE);
 
-               r_o.ctr = ctr;
+               s = unistr2_tdup(mem_ctx, &info1_str->uni_remark);
+               if (s)
+                       init_unistr2(&info1_str->uni_remark,
+                                    s, UNI_STR_TERMINATE);
 
-               srv_io_r_net_share_enum("", &r_o, &rdata, 0);
-               p = rdata.offset != 0;
+               break;
+       }
+       case 2:
+       {
+               SRV_SHARE_INFO_2 *info2 = &info->share.info2;
+               SH_INFO_2_STR *info2_str = &info2->info_2_str;
                
-               if (p && r_o.status != 0)
-               {
-                       /* report error code */
-                       DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
-                       p = 0;
-               }
+               char *s;
 
-               if (p && r_o.ctr->switch_value != switch_value)
-               {
-                       /* different switch levels.  oops. */
-                       DEBUG(0,("SRV_R_NET_SRV_SHARE_ENUM: info class %d does not match request %d\n",
-                               r_o.ctr->switch_value, switch_value));
-                       p = 0;
-               }
+               info->share.info2 = r.info.share.info2;
 
-               if (p)
-               {
-                       /* ok, at last: we're happy. */
-                       valid_enum = True;
-               }
+               /* Duplicate strings */
+
+               s = unistr2_tdup(mem_ctx, &info2_str->uni_netname);
+               if (s)
+                       init_unistr2(&info2_str->uni_netname,
+                                    s, UNI_STR_TERMINATE);
+
+               s = unistr2_tdup(mem_ctx, &info2_str->uni_remark);
+               if (s)
+                       init_unistr2(&info2_str->uni_remark,
+                                    s, UNI_STR_TERMINATE);
+
+               s = unistr2_tdup(mem_ctx, &info2_str->uni_path);
+               if (s)
+                       init_unistr2(&info2_str->uni_path,
+                                    s, UNI_STR_TERMINATE);
+
+               s = unistr2_tdup(mem_ctx, &info2_str->uni_passwd);
+               if (s)
+                       init_unistr2(&info2_str->uni_passwd,
+                                    s, UNI_STR_TERMINATE);
+
+
+               break;
        }
+       case 502:
+       {
+               SRV_SHARE_INFO_502 *info502 = &info->share.info502;
+               SH_INFO_502_STR *info502_str = &info502->info_502_str;
+               
+               char *s;
 
-       prs_mem_free(&data   );
-       prs_mem_free(&rdata  );
-       
-       return valid_enum;
+               info->share.info502 = r.info.share.info502;
+
+               /* Duplicate strings */
+
+               s = unistr2_tdup(mem_ctx, &info502_str->uni_netname);
+               if (s)
+                       init_unistr2(&info502_str->uni_netname,
+                                    s, UNI_STR_TERMINATE);
+
+               s = unistr2_tdup(mem_ctx, &info502_str->uni_remark);
+               if (s)
+                       init_unistr2(&info502_str->uni_remark,
+                                    s, UNI_STR_TERMINATE);
+
+               s = unistr2_tdup(mem_ctx, &info502_str->uni_path);
+               if (s)
+                       init_unistr2(&info502_str->uni_path,
+                                    s, UNI_STR_TERMINATE);
+
+               s = unistr2_tdup(mem_ctx, &info502_str->uni_passwd);
+               if (s)
+                       init_unistr2(&info502_str->uni_passwd,
+                                    s, UNI_STR_TERMINATE);
+
+               info502_str->sd = dup_sec_desc(mem_ctx, info502_str->sd);
+               break;
+       }
+       default:
+               DEBUG(0,("unimplemented info-level: %d\n", info_level));
+               break;
+       }
+
+  done:
+
+       return result;
 }
 
-/****************************************************************************
-do a server net file enum
-****************************************************************************/
-BOOL do_srv_net_srv_file_enum(struct cli_state *cli, uint16 fnum,
-                       char *server_name, char *qual_name, uint32 file_id,
-                       uint32 switch_value, SRV_FILE_INFO_CTR *ctr,
-                       uint32 preferred_len,
-                       ENUM_HND *hnd)
+WERROR rpccli_srvsvc_net_share_set_info(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx,
+                                    const char *sharename,
+                                    uint32 info_level,
+                                    SRV_SHARE_INFO *info)
 {
-       prs_struct data; 
-       prs_struct rdata;
-       SRV_Q_NET_FILE_ENUM q_o;
-    BOOL valid_enum = False;
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_SHARE_SET_INFO q;
+       SRV_R_NET_SHARE_SET_INFO r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
-       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
-       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
-       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+       /* Initialise input parameters */
 
-       /* create and send a MSRPC command with api SRV_NETFILEENUM */
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       DEBUG(4,("SRV Get File Info (%s), level %d, enum:%8x\n",
-                               server_name, switch_value, get_enum_hnd(hnd)));
-                               
-       q_o.file_level = switch_value;
+       init_srv_q_net_share_set_info(&q, server, sharename, info_level, info);
 
-       ctr->switch_value = switch_value;
-       ctr->ptr_file_ctr = 1;
-       ctr->file.info3.num_entries_read = 0;
-       ctr->file.info3.ptr_file_info    = 1;
+       /* Marshall data and send request */
 
-       /* store the parameters */
-       make_srv_q_net_file_enum(&q_o, server_name, qual_name, file_id,
-                                switch_value, ctr,
-                                preferred_len,
-                                hnd);
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_SET_INFO,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_set_info,
+               srv_io_r_net_share_set_info,
+               WERR_GENERAL_FAILURE);
 
-       /* turn parameters into data stream */
-       srv_io_q_net_file_enum("", &q_o, &data, 0);
+       result = r.status;
+       return result;
+}
 
-       /* send the data on \PIPE\ */
-       if (rpc_api_pipe_req(cli, fnum, SRV_NETFILEENUM, &data, &rdata))
-       {
-               SRV_R_NET_FILE_ENUM r_o;
-               BOOL p;
+WERROR rpccli_srvsvc_net_share_del(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                               const char *sharename)
+{
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_SHARE_DEL q;
+       SRV_R_NET_SHARE_DEL r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
-               r_o.ctr = ctr;
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
-               srv_io_r_net_file_enum("", &r_o, &rdata, 0);
-               p = rdata.offset != 0;
-               
-               if (p && r_o.status != 0)
-               {
-                       /* report error code */
-                       DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
-                       p = 0;
-               }
+       /* Initialise input parameters */
 
-               if (p && r_o.ctr->switch_value != switch_value)
-               {
-                       /* different switch levels.  oops. */
-                       DEBUG(0,("SRV_R_NET_SRV_FILE_ENUM: info class %d does not match request %d\n",
-                               r_o.ctr->switch_value, switch_value));
-                       p = 0;
-               }
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-               if (p)
-               {
-                       /* ok, at last: we're happy. */
-                       valid_enum = True;
-               }
-       }
+       init_srv_q_net_share_del(&q, server, sharename);
 
-       prs_mem_free(&data   );
-       prs_mem_free(&rdata  );
-       
-       return valid_enum;
+       /* Marshall data and send request */
+
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_DEL,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_del,
+               srv_io_r_net_share_del,
+               WERR_GENERAL_FAILURE);
+
+       result = r.status;
+       return result;
 }
 
-/****************************************************************************
-do a server get info 
-****************************************************************************/
-BOOL do_srv_net_srv_get_info(struct cli_state *cli, uint16 fnum,
-                       char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr)
+WERROR rpccli_srvsvc_net_share_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                               const char *netname, uint32 type, 
+                               const char *remark, uint32 perms, 
+                               uint32 max_uses, uint32 num_uses, 
+                               const char *path, const char *passwd,
+                               int level, SEC_DESC *sd)
 {
-       prs_struct data; 
-       prs_struct rdata;
-       SRV_Q_NET_SRV_GET_INFO q_o;
-    BOOL valid_info = False;
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_SHARE_ADD q;
+       SRV_R_NET_SHARE_ADD r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
-       if (server_name == NULL || switch_value == 0 || ctr == NULL) return False;
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
-       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
-       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       /* create and send a MSRPC command with api SRV_NET_SRV_GET_INFO */
+       init_srv_q_net_share_add(&q,server, netname, type, remark,
+                                perms, max_uses, num_uses, path, passwd, 
+                                level, sd);
 
-       DEBUG(4,("SRV Get Server Info (%s), level %d\n", server_name, switch_value));
+       /* Marshall data and send request */
 
-       /* store the parameters */
-       make_srv_q_net_srv_get_info(&q_o, server_name, switch_value);
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_ADD,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_add,
+               srv_io_r_net_share_add,
+               WERR_GENERAL_FAILURE);
 
-       /* turn parameters into data stream */
-       srv_io_q_net_srv_get_info("", &q_o, &data, 0);
+       result = r.status;
+       return result;  
+}
 
-       /* send the data on \PIPE\ */
-       if (rpc_api_pipe_req(cli, fnum, SRV_NET_SRV_GET_INFO, &data, &rdata))
-       {
-               SRV_R_NET_SRV_GET_INFO r_o;
-               BOOL p;
+WERROR rpccli_srvsvc_net_remote_tod(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                char *server, TIME_OF_DAY_INFO *tod)
+{
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_REMOTE_TOD q;
+       SRV_R_NET_REMOTE_TOD r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server_slash;
 
-               r_o.ctr = ctr;
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
-               srv_io_r_net_srv_get_info("", &r_o, &rdata, 0);
-               p = rdata.offset != 0;
-               p = rdata.offset != 0;
-               
-               if (p && r_o.status != 0)
-               {
-                       /* report error code */
-                       DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
-                       p = 0;
-               }
+       /* Initialise input parameters */
 
-               if (p && r_o.ctr->switch_value != q_o.switch_value)
-               {
-                       /* different switch levels.  oops. */
-                       DEBUG(0,("SRV_R_NET_SRV_GET_INFO: info class %d does not match request %d\n",
-                               r_o.ctr->switch_value, q_o.switch_value));
-                       p = 0;
-               }
+       slprintf(server_slash, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server_slash);
 
-               if (p)
-               {
-                       /* ok, at last: we're happy. */
-                       valid_info = True;
-               }
-       }
+       init_srv_q_net_remote_tod(&q, server_slash);
+       r.tod = tod;
 
-       prs_mem_free(&data   );
-       prs_mem_free(&rdata  );
-       
-       return valid_info;
+       /* Marshall data and send request */
+
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_REMOTE_TOD,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_remote_tod,
+               srv_io_r_net_remote_tod,
+               WERR_GENERAL_FAILURE);
+
+       result = r.status;
+       return result;  
 }
 
-/****************************************************************************
-get server time
-****************************************************************************/
-BOOL do_srv_net_remote_tod(struct cli_state *cli, uint16 fnum,
-                          char *server_name, TIME_OF_DAY_INFO *tod)
+WERROR rpccli_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                               uint32 file_level, const char *user_name,
+                               SRV_FILE_INFO_CTR *ctr, int preferred_len,
+                               ENUM_HND *hnd)
 {
-       prs_struct data; 
-       prs_struct rdata;
-       SRV_Q_NET_REMOTE_TOD q_t;
-       BOOL valid_info = False;
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_FILE_ENUM q;
+       SRV_R_NET_FILE_ENUM r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
+       int i;
 
-       if (server_name == NULL || tod == NULL) return False;
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
-       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
-       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+       /* Initialise input parameters */
 
-       /* create and send a MSRPC command with api SRV_NET_REMOTE_TOD */
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       DEBUG(4,("SRV Remote TOD (%s)\n", server_name));
+       init_srv_q_net_file_enum(&q, server, NULL, user_name, 
+                                file_level, ctr, preferred_len, hnd);
 
-       /* store the parameters */
-       make_srv_q_net_remote_tod(&q_t, server_name);
+       /* Marshall data and send request */
 
-       /* turn parameters into data stream */
-       srv_io_q_net_remote_tod("", &q_t, &data, 0);
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_FILE_ENUM,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_file_enum,
+               srv_io_r_net_file_enum,
+               WERR_GENERAL_FAILURE);
 
-       /* send the data on \PIPE\ */
-       if (rpc_api_pipe_req(cli, fnum, SRV_NET_REMOTE_TOD, &data, &rdata))
-       {
-               SRV_R_NET_REMOTE_TOD r_t;
-               BOOL p;
+       result = r.status;
 
-               r_t.tod = tod;
+       if (!W_ERROR_IS_OK(result))
+               goto done;
 
-               srv_io_r_net_remote_tod("", &r_t, &rdata, 0);
-               p = rdata.offset != 0;
-               p = rdata.offset != 0;
-               
-               if (p && r_t.status != 0)
-               {
-                       /* report error code */
-                       DEBUG(0,("SRV_R_NET_REMOTE_TOD: %s\n", get_nt_error_msg(r_t.status)));
-                       p = False;
-               }
+       /* copy the data over to the ctr */
+
+       ZERO_STRUCTP(ctr);
 
-               if (p)
-               {
-                       valid_info = True;
+       ctr->level = file_level;
+
+       ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
+       
+       switch(file_level) {
+       case 3:
+               if ( (ctr->file.info3 = TALLOC_ARRAY(mem_ctx, FILE_INFO_3, ctr->num_entries)) == NULL ) {
+                       return WERR_NOMEM;
                }
+
+               memset(ctr->file.info3, 0, sizeof(FILE_INFO_3) * ctr->num_entries);
+
+               for (i = 0; i < r.ctr.num_entries; i++) {
+                       FILE_INFO_3 *info3 = &ctr->file.info3[i];
+                       char *s;
+                       
+                       /* Copy pointer crap */
+
+                       memcpy(info3, &r.ctr.file.info3[i], sizeof(FILE_INFO_3));
+
+                       /* Duplicate strings */
+
+                       if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].path)) != NULL ) {
+                               info3->path = TALLOC_P( mem_ctx, UNISTR2 );
+                               init_unistr2(info3->path, s, UNI_STR_TERMINATE);
+                       }
+               
+                       if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].user)) != NULL ) {
+                               info3->user = TALLOC_P( mem_ctx, UNISTR2 );
+                               init_unistr2(info3->user, s, UNI_STR_TERMINATE);
+                       }
+
+               }               
+
+               break;
        }
 
-       prs_mem_free(&data   );
-       prs_mem_free(&rdata  );
-       
-       return valid_info;
+  done:
+       return result;
+}
+
+WERROR rpccli_srvsvc_net_file_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                uint32 file_id)
+{
+       prs_struct qbuf, rbuf;
+       SRV_Q_NET_FILE_CLOSE q;
+       SRV_R_NET_FILE_CLOSE r;
+       WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise input parameters */
+
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
+
+       init_srv_q_net_file_close(&q, server, file_id);
+
+       /* Marshall data and send request */
+
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_FILE_CLOSE,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_file_close,
+               srv_io_r_net_file_close,
+               WERR_GENERAL_FAILURE);
+
+       result = r.status;
+       return result;
 }