summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h10
-rw-r--r--source3/include/rpc_srvsvc.h40
-rw-r--r--source3/rpc_parse/parse_misc.c31
-rw-r--r--source3/rpc_parse/parse_srv.c224
-rw-r--r--source3/rpc_server/srv_srvsvc.c62
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c131
6 files changed, 477 insertions, 21 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index ba13dd43c9..35d2793e9b 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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 */
diff --git a/source3/include/rpc_srvsvc.h b/source3/include/rpc_srvsvc.h
index 2224f38766..ffd619df41 100644
--- a/source3/include/rpc_srvsvc.h
+++ b/source3/include/rpc_srvsvc.h
@@ -36,9 +36,47 @@
#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) */
diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c
index 81602a1dc4..4b118dd2b4 100644
--- a/source3/rpc_parse/parse_misc.c
+++ b/source3/rpc_parse/parse_misc.c
@@ -1457,6 +1457,37 @@ BOOL smb_io_pol_hnd(char *desc, POLICY_HND *pol, prs_struct *ps, int depth)
}
/*******************************************************************
+ 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.
********************************************************************/
diff --git a/source3/rpc_parse/parse_srv.c b/source3/rpc_parse/parse_srv.c
index 61d2ff7ba2..4abd93b159 100644
--- a/source3/rpc_parse/parse_srv.c
+++ b/source3/rpc_parse/parse_srv.c
@@ -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;
+}
diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c
index d4d5e1bfe8..76542d1c2f 100644
--- a/source3/rpc_server/srv_srvsvc.c
+++ b/source3/rpc_server/srv_srvsvc.c
@@ -345,6 +345,66 @@ static BOOL api_srv_net_remote_tod(pipes_struct *p)
}
/*******************************************************************
+ 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 }
};
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 887c100d57..48961dcb64 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -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;
+}