From 8bd2a11c86ddc3bbb2bec32415e027d87df639af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 May 2001 01:01:19 +0000 Subject: Added code from "Nigel Williams" (yes, the same famous 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. (This used to be commit 9b3dd801765fad28c0f9d58e5af2537cfccdd4ee) --- source3/include/proto.h | 10 +- source3/include/rpc_srvsvc.h | 40 +++++++ source3/rpc_parse/parse_misc.c | 31 +++++ source3/rpc_parse/parse_srv.c | 224 +++++++++++++++++++++++++++++++++---- source3/rpc_server/srv_srvsvc.c | 62 ++++++++++ source3/rpc_server/srv_srvsvc_nt.c | 131 +++++++++++++++++++++- 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 @@ -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. ********************************************************************/ 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 @@ -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 } }; 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" . +/***********************************************************************************/ + +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; +} -- cgit