]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Added code from "Nigel Williams" <nigel@veritas.com> (yes, the same famous
authorJeremy Allison <jra@samba.org>
Tue, 1 May 2001 01:01:19 +0000 (01:01 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 1 May 2001 01:01:19 +0000 (01:01 +0000)
Nigel Williams who did NIS/GINA !) to implement add/modify/delete shares
for Win2k. Needs testing as I made a few mods to the original code.
Jeremy.

source/include/proto.h
source/include/rpc_srvsvc.h
source/rpc_parse/parse_misc.c
source/rpc_parse/parse_srv.c
source/rpc_server/srv_srvsvc.c
source/rpc_server/srv_srvsvc_nt.c

index ba13dd43c91332122e4db5fb265339d5c0902ff2..35d2793e9b1efb7be48c29b43611450699806fbc 100644 (file)
@@ -2566,6 +2566,7 @@ void init_owf_info(OWF_INFO *hash, uint8 data[16]);
 BOOL smb_io_owf_info(char *desc, OWF_INFO *hash, prs_struct *ps, int depth);
 BOOL smb_io_gid(char *desc,  DOM_GID *gid, prs_struct *ps, int depth);
 BOOL smb_io_pol_hnd(char *desc, POLICY_HND *pol, prs_struct *ps, int depth);
+void init_unistr3(UNISTR3 *str, const char *buf);
 BOOL smb_io_unistr3(char *desc, UNISTR3 *name, prs_struct *ps, int depth);
 BOOL prs_uint64(char *name, prs_struct *ps, int depth, UINT64_S *data64);
 
@@ -3537,7 +3538,8 @@ void init_srv_share_info502(SH_INFO_502 *sh502,
                                char *net_name, uint32 type, char *remark,
                                uint32 perms, uint32 max_uses, uint32 num_uses,
                                char *path, char *passwd, SEC_DESC *psd, size_t sd_size);
-void init_srv_share_info502_str(SH_INFO_502_STR *sh502,
+void init_srv_share_info502_str(SH_INFO_502_STR *sh502str,
+                               SH_INFO_502 *ptrs,
                                char *net_name, char *remark,
                                char *path, char *passwd, SEC_DESC *psd, size_t sd_size);
 void init_srv_q_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, 
@@ -3612,6 +3614,10 @@ void init_time_of_day_info(TIME_OF_DAY_INFO *tod, uint32 elapsedt, uint32 msecs,
                           uint32 zone, uint32 tintervals, uint32 day,
                           uint32 month, uint32 year, uint32 weekday);
 BOOL srv_io_r_net_remote_tod(char *desc, SRV_R_NET_REMOTE_TOD *r_n, prs_struct *ps, int depth);
+BOOL srv_io_q_net_disk_enum(char *desc, SRV_Q_NET_DISK_ENUM *q_n, prs_struct *ps, int depth);
+BOOL srv_io_r_net_disk_enum(char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_struct *ps, int depth);
+BOOL srv_io_q_net_name_validate(char *desc, SRV_Q_NET_NAME_VALIDATE *q_n, prs_struct *ps, int depth);
+BOOL srv_io_r_net_name_validate(char *desc, SRV_R_NET_NAME_VALIDATE *r_n, prs_struct *ps, int depth);
 
 /*The following definitions come from  rpc_parse/parse_wks.c  */
 
@@ -3835,6 +3841,8 @@ uint32 _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
 uint32 _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_SHARE_ADD *r_u);
 uint32 _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_SHARE_DEL *r_u);
 uint32 _srv_net_remote_tod(pipes_struct *p, SRV_Q_NET_REMOTE_TOD *q_u, SRV_R_NET_REMOTE_TOD *r_u);
+uint32 _srv_net_disk_enum(pipes_struct *p, SRV_Q_NET_DISK_ENUM *q_u, SRV_R_NET_DISK_ENUM *r_u);
+uint32 _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV_R_NET_NAME_VALIDATE *r_u);
 
 /*The following definitions come from  rpc_server/srv_util.c  */
 
index 2224f3876625cc561f9f1d1b11993cb0bf029bce..ffd619df41ce210f1f4e279a5a186d6dbddd432f 100644 (file)
 #define SRV_NET_SHARE_DEL      0x12
 #define SRV_NET_SRV_GET_INFO   0x15
 #define SRV_NET_SRV_SET_INFO   0x16
+#define SRV_NET_DISK_ENUM      0x17
 #define SRV_NET_REMOTE_TOD     0x1c
+#define SRV_NET_NAME_VALIDATE  0x21
 #define SRV_NETSHAREENUM       0x24
 
+#define MAX_SERVER_DISK_ENTRIES 15
+
+typedef struct disk_info {
+       uint32  unknown;
+       UNISTR3 disk_name;
+} DISK_INFO;
+
+typedef struct disk_enum_container {
+       uint32 level;
+       uint32 entries_read;
+       uint32 unknown;
+       uint32 disk_info_ptr;
+       DISK_INFO disk_info[MAX_SERVER_DISK_ENTRIES];
+} DISK_ENUM_CONTAINER;
+
+typedef struct net_srv_disk_enum {
+       uint32 ptr_srv_name;         /* pointer (to server name?) */
+       UNISTR2 uni_srv_name;        /* server name */
+
+       DISK_ENUM_CONTAINER disk_enum_ctr;
+
+       uint32 preferred_len;        /* preferred maximum length (0xffff ffff) */
+       uint32 total_entries;        /* total number of entries */
+       ENUM_HND enum_hnd;
+       uint32 status;               /* return status */
+} SRV_Q_NET_DISK_ENUM, SRV_R_NET_DISK_ENUM;
+
+typedef struct net_name_validate {
+       uint32 ptr_srv_name;
+       UNISTR2 uni_srv_name;
+       UNISTR2 uni_name; /*name to validate*/
+       uint32 type;
+       uint32 flags;
+       uint32 status;
+} SRV_Q_NET_NAME_VALIDATE, SRV_R_NET_NAME_VALIDATE;
+
 /* SESS_INFO_0 (pointers to level 0 session info strings) */
 typedef struct ptr_sess_info0
 {
@@ -328,6 +366,8 @@ typedef struct ptr_share_info502
 /* SH_INFO_502_STR (level 502 share info strings) */
 typedef struct str_share_info502
 {
+       SH_INFO_502 *ptrs;
+
        UNISTR2 uni_netname; /* unicode string of net name (e.g NETLOGON) */
        UNISTR2 uni_remark;  /* unicode string of comment (e.g "Logon server share") */
        UNISTR2 uni_path;    /* unicode string of local path (e.g c:\winnt\system32\repl\import\scripts) */
index 81602a1dc407f43259b202e2d660f606b5b4420b..4b118dd2b45de243a053931ca94f8beceec64ca9 100644 (file)
@@ -1456,6 +1456,37 @@ BOOL smb_io_pol_hnd(char *desc, POLICY_HND *pol, prs_struct *ps, int depth)
        return True;
 }
 
+/*******************************************************************
+ Create a UNISTR3.
+********************************************************************/
+
+void init_unistr3(UNISTR3 *str, const char *buf)
+{
+       size_t len;
+
+       if (buf == NULL) {
+               str->uni_str_len=0;
+               str->str.buffer = NULL;
+               return;
+       }
+
+       len = strlen(buf) + 1;
+
+       str->uni_str_len=len;
+
+       if (len < MAX_UNISTRLEN)
+               len = MAX_UNISTRLEN;
+
+       len *= sizeof(uint16);
+
+       str->str.buffer = (uint16 *)talloc_zero(get_talloc_ctx(), len);
+       if (str->str.buffer == NULL)
+               smb_panic("init_unistr3: malloc fail\n");
+
+       /* store the string (null-terminated copy) */
+       dos_struni2((char *)str->str.buffer, buf, len);
+}
+
 /*******************************************************************
  Reads or writes a UNISTR3 structure.
 ********************************************************************/
index 61d2ff7ba2a48035200e52906804c0616b01fe4d..4abd93b1592f6181cd9a5cf8bee18d135c9e2220 100644 (file)
@@ -280,18 +280,27 @@ static BOOL srv_io_share_info502(char *desc, SH_INFO_502 *sh502, prs_struct *ps,
  Inits a SH_INFO_502_STR structure
 ********************************************************************/
 
-void init_srv_share_info502_str(SH_INFO_502_STR *sh502,
+void init_srv_share_info502_str(SH_INFO_502_STR *sh502str,
+                               SH_INFO_502 *ptrs,
                                char *net_name, char *remark,
                                char *path, char *passwd, SEC_DESC *psd, size_t sd_size)
 {
        DEBUG(5,("init_srv_share_info502_str\n"));
 
-       init_unistr2(&sh502->uni_netname, net_name, strlen(net_name)+1);
-       init_unistr2(&sh502->uni_remark, remark, strlen(remark)+1);
-       init_unistr2(&sh502->uni_path, path, strlen(path)+1);
-       init_unistr2(&sh502->uni_passwd, passwd, strlen(passwd)+1);
-       sh502->sd = psd;
-       sh502->sd_size = sd_size;
+       sh502str->ptrs = ptrs;
+
+       if(sh502str->ptrs->ptr_netname)
+               init_unistr2(&sh502str->uni_netname, net_name, strlen(net_name)+1);
+       if(sh502str->ptrs->ptr_remark)
+               init_unistr2(&sh502str->uni_remark, remark, strlen(remark)+1);
+       if(sh502str->ptrs->ptr_path)
+               init_unistr2(&sh502str->uni_path, path, strlen(path)+1);
+       if(sh502str->ptrs->ptr_passwd)
+               init_unistr2(&sh502str->uni_passwd, passwd, strlen(passwd)+1);
+       if(sh502str->ptrs->ptr_sd) {
+               sh502str->sd = psd;
+               sh502str->sd_size = sd_size;
+       }
 }
 
 /*******************************************************************
@@ -308,31 +317,45 @@ static BOOL srv_io_share_info502_str(char *desc, SH_INFO_502_STR *sh502, prs_str
 
        if(!prs_align(ps))
                return False;
-       if(!smb_io_unistr2("", &sh502->uni_netname, True, ps, depth))
-               return False;
+
+       if(sh502->ptrs->ptr_netname) {
+               if(!smb_io_unistr2("", &sh502->uni_netname, True, ps, depth))
+                       return False;
+       }
 
        if(!prs_align(ps))
                return False;
-       if(!smb_io_unistr2("", &sh502->uni_remark, True, ps, depth))
-               return False;
+
+       if(sh502->ptrs->ptr_remark) {
+               if(!smb_io_unistr2("", &sh502->uni_remark, True, ps, depth))
+                       return False;
+       }
 
        if(!prs_align(ps))
                return False;
-       if(!smb_io_unistr2("", &sh502->uni_path, True, ps, depth))
-               return False;
+
+       if(sh502->ptrs->ptr_path) {
+               if(!smb_io_unistr2("", &sh502->uni_path, True, ps, depth))
+                       return False;
+       }
 
        if(!prs_align(ps))
                return False;
-       if(!smb_io_unistr2("", &sh502->uni_passwd, True, ps, depth))
-               return False;
+
+       if(sh502->ptrs->ptr_passwd) {
+               if(!smb_io_unistr2("", &sh502->uni_passwd, True, ps, depth))
+                       return False;
+       }
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("sd_size   ", ps, depth, &sh502->sd_size))
-               return False;
-       if (!sec_io_desc(desc, &sh502->sd, ps, depth))
-               return False;
+       if(sh502->ptrs->ptr_sd) {
+               if(!prs_uint32("sd_size   ", ps, depth, &sh502->sd_size))
+                       return False;
+               if (!sec_io_desc(desc, &sh502->sd, ps, depth))
+                       return False;
+       }
 
        return True;
 }
@@ -501,6 +524,7 @@ static BOOL srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct
                }
 
                for (i = 0; i < num_entries; i++) {
+                       info502[i].info_502_str.ptrs = &info502[i].info_502;
                        if(!srv_io_share_info502_str("", &info502[i].info_502_str, ps, depth))
                                return False;
                }
@@ -675,6 +699,9 @@ static BOOL srv_io_srv_share_info(char *desc, prs_struct *ps, int depth, SRV_SHA
                        if(!srv_io_share_info502("", &r_n->share.info502.info_502, ps, depth))
                                return False;
 
+                       /*allow access to pointers in the str part. */
+                       r_n->share.info502.info_502_str.ptrs = &r_n->share.info502.info_502;
+
                        if(!srv_io_share_info502_str("", &r_n->share.info502.info_502_str, ps, depth))
                                return False;
                        break;
@@ -2374,3 +2401,162 @@ BOOL srv_io_r_net_remote_tod(char *desc, SRV_R_NET_REMOTE_TOD *r_n, prs_struct *
 
        return True;
 }
+
+/*******************************************************************
+ Reads or writes a structure.
+ ********************************************************************/
+
+BOOL srv_io_q_net_disk_enum(char *desc, SRV_Q_NET_DISK_ENUM *q_n, prs_struct *ps, int depth)
+{
+       if (q_n == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_disk_enum");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
+               return False;
+
+       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("level", ps, depth, &q_n->disk_enum_ctr.level))
+               return False;
+
+       if(!prs_uint32("entries_read", ps, depth, &q_n->disk_enum_ctr.entries_read))
+               return False;
+
+       if(!prs_uint32("buffer", ps, depth, &q_n->disk_enum_ctr.disk_info_ptr))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len))
+               return False;
+       if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+ ********************************************************************/
+
+BOOL srv_io_r_net_disk_enum(char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (r_n == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_r_net_disk_enum");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("entries_read", ps, depth, &r_n->disk_enum_ctr.entries_read))
+               return False;
+       if(!prs_uint32("ptr_disk_info", ps, depth, &r_n->disk_enum_ctr.disk_info_ptr))
+               return False;
+
+       /*this may be max, unknown, actual?*/
+
+       if(!prs_uint32("max_elements", ps, depth, &r_n->disk_enum_ctr.entries_read))
+               return False;
+       if(!prs_uint32("unknown", ps, depth, &r_n->disk_enum_ctr.unknown))
+               return False;
+       if(!prs_uint32("actual_elements", ps, depth, &r_n->disk_enum_ctr.entries_read))
+               return False;
+
+       for(i=0; i < r_n->disk_enum_ctr.entries_read; i++) {
+
+               if(!prs_uint32("unknown", ps, depth, &r_n->disk_enum_ctr.disk_info[i].unknown))
+                       return False;
+   
+               if(!smb_io_unistr3("disk_name", &r_n->disk_enum_ctr.disk_info[i].disk_name, ps, depth))
+                       return False;
+
+               if(!prs_align(ps))
+                       return False;
+       }
+
+       if(!prs_uint32("total_entries", ps, depth, &r_n->total_entries))
+               return False;
+
+       if(!smb_io_enum_hnd("enum_hnd", &r_n->enum_hnd, ps, depth))
+               return False;
+
+       if(!prs_uint32("status", ps, depth, &r_n->status))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+ ********************************************************************/
+
+BOOL srv_io_q_net_name_validate(char *desc, SRV_Q_NET_NAME_VALIDATE *q_n, prs_struct *ps, int depth)
+{
+       if (q_n == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_name_validate");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
+               return False;
+
+       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_unistr2("", &q_n->uni_name, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("type", ps, depth, &q_n->type))
+               return False;
+
+       if(!prs_uint32("flags", ps, depth, &q_n->flags))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+ ********************************************************************/
+
+BOOL srv_io_r_net_name_validate(char *desc, SRV_R_NET_NAME_VALIDATE *r_n, prs_struct *ps, int depth)
+{
+       if (r_n == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_r_net_name_validate");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("status", ps, depth, &r_n->status))
+               return False;
+
+       return True;
+}
index d4d5e1bfe86253a43168d4756f3640be27776222..76542d1c2f6d21b8b9d90bc9748e54b1dc761042 100644 (file)
@@ -344,6 +344,66 @@ static BOOL api_srv_net_remote_tod(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+ RPC to enumerate disks available on a server e.g. C:, D: ...
+*******************************************************************/
+
+static BOOL api_srv_net_disk_enum(pipes_struct *p) 
+{
+       SRV_Q_NET_DISK_ENUM q_u;
+       SRV_R_NET_DISK_ENUM r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* Unmarshall the net server disk enum. */
+       if(!srv_io_q_net_disk_enum("", &q_u, data, 0)) {
+               DEBUG(0,("api_srv_net_disk_enum: Failed to unmarshall SRV_Q_NET_DISK_ENUM.\n"));
+               return False;
+       }
+
+       r_u.status = _srv_net_disk_enum(p, &q_u, &r_u);
+
+       if(!srv_io_r_net_disk_enum("", &r_u, rdata, 0)) {
+               DEBUG(0,("api_srv_net_disk_enum: Failed to marshall SRV_R_NET_DISK_ENUM.\n"));
+               return False;
+       }
+
+       return True;
+}
+
+/*******************************************************************
+ NetValidateName (opnum 0x21) 
+*******************************************************************/
+
+static BOOL api_srv_net_name_validate(pipes_struct *p) 
+{
+       SRV_Q_NET_NAME_VALIDATE q_u;
+       SRV_R_NET_NAME_VALIDATE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+  
+       /* Unmarshall the net server disk enum. */
+       if(!srv_io_q_net_name_validate("", &q_u, data, 0)) {
+               DEBUG(0,("api_srv_net_name_validate: Failed to unmarshall SRV_Q_NET_NAME_VALIDATE.\n"));
+               return False;
+       }
+
+       r_u.status = _srv_net_name_validate(p, &q_u, &r_u);
+
+       if(!srv_io_r_net_name_validate("", &r_u, rdata, 0)) {
+               DEBUG(0,("api_srv_net_name_validate: Failed to marshall SRV_R_NET_NAME_VALIDATE.\n"));
+               return False;
+       }
+
+       return True;
+}
+
 /*******************************************************************
 \PIPE\srvsvc commands
 ********************************************************************/
@@ -361,6 +421,8 @@ struct api_struct api_srv_cmds[] =
        { "SRV_NETFILEENUM"       , SRV_NETFILEENUM       , api_srv_net_file_enum    },
        { "SRV_NET_SRV_GET_INFO"  , SRV_NET_SRV_GET_INFO  , api_srv_net_srv_get_info },
        { "SRV_NET_REMOTE_TOD"    , SRV_NET_REMOTE_TOD    , api_srv_net_remote_tod   },
+       { "SRV_NET_DISK_ENUM"     , SRV_NET_DISK_ENUM     , api_srv_net_disk_enum    },
+       { "SRV_NET_NAME_VALIDATE" , SRV_NET_NAME_VALIDATE , api_srv_net_name_validate},
        { NULL                    , 0                     , NULL                     }
 };
 
index 887c100d5773a30aecc9a6f38aeda451d4025b56..48961dcb647a72563749e66a37526e7f65802db3 100644 (file)
@@ -77,6 +77,14 @@ static void init_srv_share_info_2(SRV_SHARE_INFO_2 *sh2, int snum)
        pstring_sub(remark,"%S",lp_servicename(snum));
        pstrcpy(path, "C:");
        pstrcat(path, lp_pathname(snum));
+
+       /*
+        * Change / to \\ so that win2k will see it as a valid path.  This was added to
+        * enable use of browsing in win2k add share dialog.
+        */ 
+
+       string_replace(path, '/', '\\');
+
        pstrcpy(passwd, "");
        len_net_name = strlen(net_name);
 
@@ -363,6 +371,14 @@ static void init_srv_share_info_502(TALLOC_CTX *ctx, SRV_SHARE_INFO_502 *sh502,
        pstring_sub(remark,"%S",lp_servicename(snum));
        pstrcpy(path, "C:");
        pstrcat(path, lp_pathname(snum));
+
+       /*
+        * Change / to \\ so that win2k will see it as a valid path.  This was added to
+        * enable use of browsing in win2k add share dialog.
+        */ 
+
+       string_replace(path, '/', '\\');
+
        pstrcpy(passwd, "");
        len_net_name = strlen(net_name);
 
@@ -379,7 +395,7 @@ static void init_srv_share_info_502(TALLOC_CTX *ctx, SRV_SHARE_INFO_502 *sh502,
        sd = get_share_security(ctx, snum, &sd_size);
 
        init_srv_share_info502(&sh502->info_502, net_name, type, remark, 0, 0xffffffff, 1, path, passwd, sd, sd_size);
-       init_srv_share_info502_str(&sh502->info_502_str, net_name, remark, path, passwd, sd, sd_size);
+       init_srv_share_info502_str(&sh502->info_502_str, &sh502->info_502, net_name, remark, path, passwd, sd, sd_size);
 }
 
 /***************************************************************************
@@ -1546,3 +1562,116 @@ uint32 _srv_net_remote_tod(pipes_struct *p, SRV_Q_NET_REMOTE_TOD *q_u, SRV_R_NET
 
        return r_u->status;
 }
+
+/***********************************************************************************
+ It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
+ We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
+ These disks would the disks listed by this function.
+ Users could then create shares relative to these disks.  Watch out for moving these disks around.
+ "Nigel Williams" <nigel@veritas.com>.
+/***********************************************************************************/
+
+const char *server_disks[] = {"C:"};
+
+static uint32 get_server_disk_count(void)
+{
+       return sizeof(server_disks)/sizeof(server_disks[0]);
+}
+
+static uint32 init_server_disk_enum(uint32 *resume)
+{
+       uint32 server_disk_count = get_server_disk_count();
+
+       /*resume can be an offset into the list for now*/
+
+       if(*resume < 0)
+               *resume = 0;
+
+       if(*resume > server_disk_count)
+               *resume = server_disk_count;
+
+       return server_disk_count - *resume;
+}
+
+static const char *next_server_disk_enum(uint32 *resume)
+{
+       const char *disk;
+
+       if(init_server_disk_enum(resume) == 0)
+               return NULL;
+
+       disk = server_disks[*resume];
+
+       (*resume)++;
+
+       DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
+
+       return disk;
+}
+
+uint32 _srv_net_disk_enum(pipes_struct *p, SRV_Q_NET_DISK_ENUM *q_u, SRV_R_NET_DISK_ENUM *r_u)
+{
+       uint32 i;
+       const char *disk_name;
+       uint32 resume=get_enum_hnd(&q_u->enum_hnd);
+
+       r_u->status=NT_STATUS_NOPROBLEMO;
+
+       r_u->total_entries = init_server_disk_enum(&resume);
+
+       r_u->disk_enum_ctr.unknown = 0; 
+
+       r_u->disk_enum_ctr.disk_info_ptr = (uint32) r_u->disk_enum_ctr.disk_info;
+
+       /*allow one DISK_INFO for null terminator*/
+
+       for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
+
+               r_u->disk_enum_ctr.entries_read++;
+
+               /*copy disk name into a unicode string*/
+
+               init_unistr3(&r_u->disk_enum_ctr.disk_info[i].disk_name, disk_name);    
+       }
+
+       /*add a terminating null string.  Is this there if there is more data to come?*/
+
+       r_u->disk_enum_ctr.entries_read++;
+
+       init_unistr3(&r_u->disk_enum_ctr.disk_info[i].disk_name, "");
+
+       init_enum_hnd(&r_u->enum_hnd, resume);
+
+       return r_u->status;
+}
+
+uint32 _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV_R_NET_NAME_VALIDATE *r_u)
+{
+       int snum;
+       fstring share_name;
+
+       r_u->status=NT_STATUS_NOPROBLEMO;
+
+       switch(q_u->type) {
+
+       case 0x9:
+
+               /*check if share name is ok*/
+               /*also check if we already have a share with this name*/
+
+               unistr2_to_ascii(share_name, &q_u->uni_name, sizeof(share_name));
+               snum = find_service(share_name);
+
+               /* Share already exists. */
+               if (snum >= 0)
+                       r_u->status = NT_STATUS_OBJECT_NAME_INVALID;
+               break;
+
+       default:
+               /*unsupported type*/
+               r_u->status = ERROR_INVALID_LEVEL;
+               break;
+       }
+
+       return r_u->status;
+}