After a long chat with Luke (a pleasant one actually, thanks for asking :-),
authorJeremy Allison <jra@samba.org>
Wed, 24 Feb 1999 19:11:28 +0000 (19:11 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 24 Feb 1999 19:11:28 +0000 (19:11 +0000)
he is happy with me reverting the RPC change.

The reason I need this code in the 2.0 branch (even though it doesn't
work correctly) is I am using it as a stable area that no-one cares
about (as it doesn't work) to write the fully error checked version
of the RPC transport and parsing code.

Having it removed caused me a few problems :-).

Jeremy.

29 files changed:
source/Makefile.in
source/include/proto.h
source/include/rpc_reg.h
source/include/rpc_samr.h
source/lib/util.c
source/lsarpcd/srv_lsa.c
source/param/loadparm.c
source/rpc_client/cli_lsarpc.c
source/rpc_client/cli_reg.c
source/rpc_client/cli_samr.c
source/rpc_client/cli_srvsvc.c
source/rpc_client/cli_wkssvc.c
source/rpc_parse/parse_lsa.c
source/rpc_parse/parse_reg.c
source/rpc_parse/parse_samr.c
source/rpc_parse/parse_srv.c
source/rpc_server/srv_lsa.c
source/rpc_server/srv_pipe.c
source/rpc_server/srv_reg.c
source/rpc_server/srv_samr.c
source/rpc_server/srv_srvsvc.c
source/rpcclient/cmd_lsarpc.c
source/rpcclient/cmd_netlogon.c
source/rpcclient/cmd_reg.c
source/rpcclient/cmd_samr.c
source/rpcclient/cmd_srvsvc.c
source/rpcclient/cmd_wkssvc.c
source/rpcclient/display.c
source/rpcclient/rpcclient.c

index 905da3f1f27b809662f5e8d3d2cd443ad8ce3e9b..882a4169338b8e864fc52afc9344d0a358b92452 100644 (file)
@@ -78,7 +78,7 @@ FLAGS32  = $(ISA32) $(FLAGS5) $(PASSWD_FLAGS)
 
 SPROGS = bin/smbd bin/nmbd bin/swat
 PROGS1 = bin/smbclient bin/testparm bin/testprns bin/smbstatus @RUNPROG@
-PROGS2 = bin/smbpasswd bin/make_smbcodepage @WRAP@ @WRAP32@
+PROGS2 = bin/rpcclient bin/smbpasswd bin/make_smbcodepage @WRAP@ @WRAP32@
 MPROGS = @MPROGS@
 PROGS = $(PROGS1) $(PROGS2) $(MPROGS) bin/nmblookup bin/make_printerdef 
 
@@ -112,23 +112,26 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/namequery.o libsmb/nmblib.o \
 
 RPC_SERVER_OBJ = rpc_server/srv_lsa.o \
                  rpc_server/srv_lsa_hnd.o rpc_server/srv_netlog.o \
-                 rpc_server/srv_pipe_hnd.o \
-                 rpc_server/srv_srvsvc.o \
-                 rpc_server/srv_wkssvc.o \
-                 rpc_server/srv_util.o \
+                 rpc_server/srv_pipe_hnd.o rpc_server/srv_reg.o \
+                 rpc_server/srv_samr.o rpc_server/srv_srvsvc.o \
+                 rpc_server/srv_util.o rpc_server/srv_wkssvc.o \
                rpc_server/srv_pipe.o
 
 RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_misc.o \
                 rpc_parse/parse_net.o rpc_parse/parse_prs.o \
-                rpc_parse/parse_rpc.o \
-                rpc_parse/parse_srv.o rpc_parse/parse_wks.o \
-                rpc_parse/parse_sec.o
+                rpc_parse/parse_reg.o rpc_parse/parse_rpc.o \
+                rpc_parse/parse_samr.o rpc_parse/parse_srv.o \
+                rpc_parse/parse_wks.o rpc_parse/parse_sec.o
 
 RPC_CLIENT_OBJ = \
                rpc_client/cli_login.o    \
                rpc_client/cli_netlogon.o \
                rpc_client/cli_pipe.o     \
-               rpc_client/cli_lsarpc.o  
+               rpc_client/cli_lsarpc.o   \
+               rpc_client/cli_wkssvc.o   \
+               rpc_client/cli_srvsvc.o   \
+               rpc_client/cli_reg.o   \
+               rpc_client/cli_samr.o 
 
 
 LOCKING_OBJ = locking/locking.o locking/locking_shm.o locking/locking_slow.o \
@@ -196,6 +199,17 @@ TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) $(UBIQX_OBJ) \
 SMBPASSWD_OBJ = utils/smbpasswd.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(PASSDB_OBJ) \
                 $(UBIQX_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(LIB_OBJ)
 
+RPCCLIENT_OBJ = rpcclient/rpcclient.o \
+             rpcclient/display.o \
+             rpcclient/cmd_lsarpc.o \
+             rpcclient/cmd_wkssvc.o \
+             rpcclient/cmd_samr.o \
+             rpcclient/cmd_reg.o \
+             rpcclient/cmd_srvsvc.o \
+             rpcclient/cmd_netlogon.o \
+             $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
+             $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ)
+
 SMBWRAPPER_OBJ = smbwrapper/smbw.o smbwrapper/wrapped.o \
                smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \
                smbwrapper/realcalls.o smbwrapper/shared.o \
@@ -220,6 +234,16 @@ NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) \
 SMBTORTURE_OBJ = utils/torture.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
+RPCTORTURE_OBJ = utils/rpctorture.o \
+             rpcclient/display.o \
+             rpcclient/cmd_lsarpc.o \
+             rpcclient/cmd_wkssvc.o \
+             rpcclient/cmd_samr.o \
+             rpcclient/cmd_srvsvc.o \
+             rpcclient/cmd_netlogon.o \
+             $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
+             $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ)
+
 DEBUG2HTML_OBJ = utils/debug2html.o ubiqx/debugparse.o
 
 PROTO_OBJ = $(SMBD_OBJ) $(NMBD_OBJ) $(SWAT_OBJ) $(CLIENT_OBJ) \
@@ -327,6 +351,10 @@ bin/smbrun: $(SMBRUN_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(SMBRUN_OBJ) $(LDFLAGS) $(LIBS)
 
+bin/rpcclient: $(RPCCLIENT_OBJ) bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) -o $@ $(RPCCLIENT_OBJ) $(LDFLAGS) $(LIBS)
+
 bin/smbclient: $(CLIENT_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(LIBS)
@@ -375,6 +403,10 @@ bin/smbtorture: $(SMBTORTURE_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(LIBS)
 
+bin/rpctorture: $(RPCTORTURE_OBJ) bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(LDFLAGS) $(LIBS)
+
 bin/debug2html: $(DEBUG2HTML_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(LIBS)
index 85afe6087e39d7feb76ef0ce8d9cbf0fec073acf..f08a3b1103fa01c858ee401dce13aaa647dd0ce2 100644 (file)
@@ -296,6 +296,8 @@ char *tab_depth(int depth);
 int str_checksum(const char *s);
 void zero_free(void *p, size_t size);
 int set_maxfiles(int requested_max);
+void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name);
+BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name);
 
 /*The following definitions come from  lib/util_file.c  */
 
@@ -1311,6 +1313,12 @@ BOOL cli_nt_logoff(struct cli_state *cli, NET_ID_INFO_CTR *ctr);
 BOOL do_lsa_open_policy(struct cli_state *cli,
                        char *server_name, POLICY_HND *hnd,
                        BOOL sec_qos);
+BOOL do_lsa_lookup_sids(struct cli_state *cli,
+                       POLICY_HND *hnd,
+                       int num_sids,
+                       DOM_SID **sids,
+                       char ***names,
+                       int *num_names);
 BOOL do_lsa_query_info_pol(struct cli_state *cli,
                        POLICY_HND *hnd, uint16 info_class,
                        fstring domain_name, DOM_SID *domain_sid);
@@ -1336,8 +1344,123 @@ void cli_nt_set_ntlmssp_flgs(struct cli_state *cli, uint32 ntlmssp_flgs);
 BOOL cli_nt_session_open(struct cli_state *cli, char *pipe_name);
 void cli_nt_session_close(struct cli_state *cli);
 
+/*The following definitions come from  rpc_client/cli_reg.c  */
+
+BOOL do_reg_connect(struct cli_state *cli, char *full_keyname, char *key_name,
+                               POLICY_HND *reg_hnd);
+BOOL do_reg_open_hklm(struct cli_state *cli, uint16 unknown_0, uint32 level,
+                               POLICY_HND *hnd);
+BOOL do_reg_open_hku(struct cli_state *cli, uint16 unknown_0, uint32 level,
+                               POLICY_HND *hnd);
+BOOL do_reg_flush_key(struct cli_state *cli, POLICY_HND *hnd);
+BOOL do_reg_query_key(struct cli_state *cli, POLICY_HND *hnd,
+                               char *class, uint32 *class_len,
+                               uint32 *num_subkeys, uint32 *max_subkeylen,
+                               uint32 *max_subkeysize, uint32 *num_values,
+                               uint32 *max_valnamelen, uint32 *max_valbufsize,
+                               uint32 *sec_desc, NTTIME *mod_time);
+BOOL do_reg_unknown_1a(struct cli_state *cli, POLICY_HND *hnd, uint32 *unk);
+BOOL do_reg_query_info(struct cli_state *cli, POLICY_HND *hnd,
+                               char *type, uint32 *unk_0, uint32 *unk_1);
+BOOL do_reg_set_key_sec(struct cli_state *cli, POLICY_HND *hnd, SEC_DESC_BUF *sec_desc_buf);
+BOOL do_reg_get_key_sec(struct cli_state *cli, POLICY_HND *hnd, uint32 *sec_buf_size, SEC_DESC_BUF **ppsec_desc_buf);
+BOOL do_reg_delete_val(struct cli_state *cli, POLICY_HND *hnd, char *val_name);
+BOOL do_reg_delete_key(struct cli_state *cli, POLICY_HND *hnd, char *key_name);
+BOOL do_reg_create_key(struct cli_state *cli, POLICY_HND *hnd,
+                               char *key_name, char *key_class,
+                               SEC_ACCESS *sam_access,
+                               POLICY_HND *key);
+BOOL do_reg_enum_key(struct cli_state *cli, POLICY_HND *hnd,
+                               int key_index, char *key_name,
+                               uint32 *unk_1, uint32 *unk_2,
+                               time_t *mod_time);
+BOOL do_reg_create_val(struct cli_state *cli, POLICY_HND *hnd,
+                               char *val_name, uint32 type, BUFFER3 *data);
+BOOL do_reg_enum_val(struct cli_state *cli, POLICY_HND *hnd,
+                               int val_index, int max_valnamelen, int max_valbufsize,
+                               fstring val_name,
+                               uint32 *val_type, BUFFER2 *value);
+BOOL do_reg_open_entry(struct cli_state *cli, POLICY_HND *hnd,
+                               char *key_name, uint32 unk_0,
+                               POLICY_HND *key_hnd);
+BOOL do_reg_close(struct cli_state *cli, POLICY_HND *hnd);
+
+/*The following definitions come from  rpc_client/cli_samr.c  */
+
+BOOL get_samr_query_usergroups(struct cli_state *cli, 
+                               POLICY_HND *pol_open_domain, uint32 user_rid,
+                               uint32 *num_groups, DOM_GID *gid);
+BOOL get_samr_query_userinfo(struct cli_state *cli, 
+                               POLICY_HND *pol_open_domain,
+                               uint32 info_level,
+                               uint32 user_rid, SAM_USER_INFO_21 *usr);
+BOOL do_samr_chgpasswd_user(struct cli_state *cli,
+               char *srv_name, char *user_name,
+               char nt_newpass[516], uchar nt_oldhash[16],
+               char lm_newpass[516], uchar lm_oldhash[16]);
+BOOL do_samr_unknown_38(struct cli_state *cli, char *srv_name);
+BOOL do_samr_query_dom_info(struct cli_state *cli, 
+                               POLICY_HND *domain_pol, uint16 switch_value);
+BOOL do_samr_enum_dom_users(struct cli_state *cli, 
+                               POLICY_HND *pol, uint16 num_entries, uint16 unk_0,
+                               uint16 acb_mask, uint16 unk_1, uint32 size,
+                               struct acct_info **sam,
+                               int *num_sam_users);
+BOOL do_samr_connect(struct cli_state *cli, 
+                               char *srv_name, uint32 unknown_0,
+                               POLICY_HND *connect_pol);
+BOOL do_samr_open_user(struct cli_state *cli, 
+                               POLICY_HND *pol, uint32 unk_0, uint32 rid, 
+                               POLICY_HND *user_pol);
+BOOL do_samr_open_domain(struct cli_state *cli, 
+                               POLICY_HND *connect_pol, uint32 rid, DOM_SID *sid,
+                               POLICY_HND *domain_pol);
+BOOL do_samr_query_unknown_12(struct cli_state *cli, 
+                               POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids,
+                               uint32 *num_aliases,
+                               fstring als_names    [MAX_LOOKUP_SIDS],
+                               uint32  num_als_users[MAX_LOOKUP_SIDS]);
+BOOL do_samr_query_usergroups(struct cli_state *cli, 
+                               POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid);
+BOOL do_samr_query_userinfo(struct cli_state *cli, 
+                               POLICY_HND *pol, uint16 switch_value, void* usr);
+BOOL do_samr_close(struct cli_state *cli, POLICY_HND *hnd);
+
+/*The following definitions come from  rpc_client/cli_srvsvc.c  */
+
+BOOL do_srv_net_srv_conn_enum(struct cli_state *cli,
+                       char *server_name, char *qual_name,
+                       uint32 switch_value, SRV_CONN_INFO_CTR *ctr,
+                       uint32 preferred_len,
+                       ENUM_HND *hnd);
+BOOL do_srv_net_srv_sess_enum(struct cli_state *cli,
+                       char *server_name, char *qual_name,
+                       uint32 switch_value, SRV_SESS_INFO_CTR *ctr,
+                       uint32 preferred_len,
+                       ENUM_HND *hnd);
+BOOL do_srv_net_srv_share_enum(struct cli_state *cli,
+                       char *server_name, 
+                       uint32 switch_value, SRV_SHARE_INFO_CTR *ctr,
+                       uint32 preferred_len,
+                       ENUM_HND *hnd);
+BOOL do_srv_net_srv_file_enum(struct cli_state *cli,
+                       char *server_name, char *qual_name,
+                       uint32 switch_value, SRV_FILE_INFO_CTR *ctr,
+                       uint32 preferred_len,
+                       ENUM_HND *hnd);
+BOOL do_srv_net_srv_get_info(struct cli_state *cli,
+                       char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr);
+
+/*The following definitions come from  rpc_client/cli_wkssvc.c  */
+
+BOOL do_wks_query_info(struct cli_state *cli, 
+                       char *server_name, uint32 switch_value,
+                       WKS_INFO_100 *wks100);
+
 /*The following definitions come from  rpc_parse/parse_lsa.c  */
 
+void make_lsa_trans_name(LSA_TRANS_NAME *trn, UNISTR2 *uni_name,
+                       uint32 sid_name_use, char *name, uint32 idx);
 void make_lsa_sec_qos(LSA_SEC_QOS *qos, uint16 imp_lev, uint8 ctxt, uint8 eff,
                                uint32 unknown);
 void make_lsa_obj_attr(LSA_OBJ_ATTR *attr, uint32 attributes, LSA_SEC_QOS *qos);
@@ -1361,6 +1484,14 @@ void make_r_enum_trust_dom(LSA_R_ENUM_TRUST_DOM *r_e,
                            uint32 status);
 void lsa_io_r_enum_trust_dom(char *desc,  LSA_R_ENUM_TRUST_DOM *r_e, prs_struct *ps, int depth);
 void lsa_io_r_query(char *desc,  LSA_R_QUERY_INFO *r_q, prs_struct *ps, int depth);
+void make_lsa_sid_enum(LSA_SID_ENUM *sen, int num_entries, DOM_SID **sids);
+void make_q_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, POLICY_HND *hnd,
+                               int num_sids, DOM_SID **sids,
+                               uint16 level);
+void lsa_io_q_lookup_sids(char *desc, LSA_Q_LOOKUP_SIDS *q_s, prs_struct *ps, int depth);
+void lsa_io_r_lookup_sids(char *desc,  LSA_R_LOOKUP_SIDS *r_s, prs_struct *ps, int depth);
+void lsa_io_q_lookup_rids(char *desc,  LSA_Q_LOOKUP_RIDS *q_r, prs_struct *ps, int depth);
+void lsa_io_r_lookup_rids(char *desc,  LSA_R_LOOKUP_RIDS *r_r, prs_struct *ps, int depth);
 void make_lsa_q_close(LSA_Q_CLOSE *q_c, POLICY_HND *hnd);
 void lsa_io_q_close(char *desc,  LSA_Q_CLOSE *q_c, prs_struct *ps, int depth);
 void lsa_io_r_close(char *desc,  LSA_R_CLOSE *r_c, prs_struct *ps, int depth);
@@ -1536,6 +1667,77 @@ BOOL prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint3
 BOOL prs_uint32_post(char *name, prs_struct *ps, int depth, uint32 *data32,
                                uint32 ptr_uint32, uint32 data_size);
 
+/*The following definitions come from  rpc_parse/parse_reg.c  */
+
+void make_reg_q_open_hklm(REG_Q_OPEN_HKLM *q_o,
+                               uint16 unknown_0, uint32 level);
+void reg_io_q_open_hklm(char *desc,  REG_Q_OPEN_HKLM *r_q, prs_struct *ps, int depth);
+void reg_io_r_open_hklm(char *desc,  REG_R_OPEN_HKLM *r_r, prs_struct *ps, int depth);
+void make_reg_q_flush_key(REG_Q_FLUSH_KEY *q_u, POLICY_HND *pol);
+void reg_io_q_flush_key(char *desc,  REG_Q_FLUSH_KEY *r_q, prs_struct *ps, int depth);
+void reg_io_r_flush_key(char *desc,  REG_R_FLUSH_KEY *r_r, prs_struct *ps, int depth);
+void make_reg_q_create_key(REG_Q_CREATE_KEY *q_c, POLICY_HND *hnd,
+                               char *name, char *class, SEC_ACCESS *sam_access,
+                               SEC_DESC_BUF *sec_buf);
+void reg_io_q_create_key(char *desc,  REG_Q_CREATE_KEY *r_q, prs_struct *ps, int depth);
+void reg_io_r_create_key(char *desc,  REG_R_CREATE_KEY *r_r, prs_struct *ps, int depth);
+void make_reg_q_delete_val(REG_Q_DELETE_VALUE *q_c, POLICY_HND *hnd,
+                               char *name);
+void reg_io_q_delete_val(char *desc,  REG_Q_DELETE_VALUE *r_q, prs_struct *ps, int depth);
+void reg_io_r_delete_val(char *desc,  REG_R_DELETE_VALUE *r_r, prs_struct *ps, int depth);
+void make_reg_q_delete_key(REG_Q_DELETE_KEY *q_c, POLICY_HND *hnd,
+                               char *name);
+void reg_io_q_delete_key(char *desc,  REG_Q_DELETE_KEY *r_q, prs_struct *ps, int depth);
+void reg_io_r_delete_key(char *desc,  REG_R_DELETE_KEY *r_r, prs_struct *ps, int depth);
+void make_reg_q_query_key(REG_Q_QUERY_KEY *q_o, POLICY_HND *hnd,
+                               uint32 max_class_len);
+void reg_io_q_query_key(char *desc,  REG_Q_QUERY_KEY *r_q, prs_struct *ps, int depth);
+void reg_io_r_query_key(char *desc,  REG_R_QUERY_KEY *r_r, prs_struct *ps, int depth);
+void make_reg_q_unk_1a(REG_Q_UNK_1A *q_o, POLICY_HND *hnd);
+void reg_io_q_unk_1a(char *desc,  REG_Q_UNK_1A *r_q, prs_struct *ps, int depth);
+void reg_io_r_unk_1a(char *desc,  REG_R_UNK_1A *r_r, prs_struct *ps, int depth);
+void make_reg_q_open_hku(REG_Q_OPEN_HKU *q_o,
+                               uint16 unknown_0, uint32 level);
+void reg_io_q_open_hku(char *desc,  REG_Q_OPEN_HKU *r_q, prs_struct *ps, int depth);
+void reg_io_r_open_hku(char *desc,  REG_R_OPEN_HKU *r_r, prs_struct *ps, int depth);
+void make_reg_q_close(REG_Q_CLOSE *q_c, POLICY_HND *hnd);
+void reg_io_q_close(char *desc,  REG_Q_CLOSE *q_u, prs_struct *ps, int depth);
+void reg_io_r_close(char *desc,  REG_R_CLOSE *r_u, prs_struct *ps, int depth);
+void make_reg_q_set_key_sec(REG_Q_SET_KEY_SEC *q_i, POLICY_HND *pol, SEC_DESC_BUF *sec_desc_buf);
+void reg_io_q_set_key_sec(char *desc,  REG_Q_SET_KEY_SEC *r_q, prs_struct *ps, int depth);
+void reg_io_r_set_key_sec(char *desc, REG_R_SET_KEY_SEC *r_q, prs_struct *ps, int depth);
+void make_reg_q_get_key_sec(REG_Q_GET_KEY_SEC *q_i, POLICY_HND *pol, 
+                               uint32 sec_buf_size, SEC_DESC_BUF *psdb);
+void reg_io_q_get_key_sec(char *desc,  REG_Q_GET_KEY_SEC *r_q, prs_struct *ps, int depth);
+void reg_io_r_get_key_sec(char *desc,  REG_R_GET_KEY_SEC *r_q, prs_struct *ps, int depth);
+void make_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, char *product_type,
+                               time_t unix_time, uint8 major, uint8 minor);
+void reg_io_q_info(char *desc,  REG_Q_INFO *r_q, prs_struct *ps, int depth);
+void make_reg_r_info(REG_R_INFO *r_r,
+                               uint32 level, char *os_type,
+                               uint32 unknown_0, uint32 unknown_1,
+                               uint32 status);
+void reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth);
+void make_reg_q_enum_val(REG_Q_ENUM_VALUE *q_i, POLICY_HND *pol,
+                               uint32 val_idx, uint32 max_val_len,
+                               uint32 max_buf_len);
+void reg_io_q_enum_val(char *desc,  REG_Q_ENUM_VALUE *q_q, prs_struct *ps, int depth);
+void reg_io_r_enum_val(char *desc,  REG_R_ENUM_VALUE *r_q, prs_struct *ps, int depth);
+void make_reg_q_create_val(REG_Q_CREATE_VALUE *q_i, POLICY_HND *pol,
+                               char *val_name, uint32 type,
+                               BUFFER3 *val);
+void reg_io_q_create_val(char *desc,  REG_Q_CREATE_VALUE *q_q, prs_struct *ps, int depth);
+void reg_io_r_create_val(char *desc,  REG_R_CREATE_VALUE *r_q, prs_struct *ps, int depth);
+void make_reg_q_enum_key(REG_Q_ENUM_KEY *q_i, POLICY_HND *pol, uint32 key_idx);
+void reg_io_q_enum_key(char *desc,  REG_Q_ENUM_KEY *q_q, prs_struct *ps, int depth);
+void reg_io_r_enum_key(char *desc,  REG_R_ENUM_KEY *r_q, prs_struct *ps, int depth);
+void make_reg_q_open_entry(REG_Q_OPEN_ENTRY *r_q, POLICY_HND *pol,
+                               char *key_name, uint32 unk);
+void reg_io_q_open_entry(char *desc,  REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int depth);
+void make_reg_r_open_entry(REG_R_OPEN_ENTRY *r_r,
+                               POLICY_HND *pol, uint32 status);
+void reg_io_r_open_entry(char *desc,  REG_R_OPEN_ENTRY *r_r, prs_struct *ps, int depth);
+
 /*The following definitions come from  rpc_parse/parse_rpc.c  */
 
 void make_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 flags,
@@ -1589,6 +1791,186 @@ void make_rpc_auth_ntlmssp_chk(RPC_AUTH_NTLMSSP_CHK *chk,
                                uint32 ver, uint32 crc32, uint32 seq_num);
 void smb_io_rpc_auth_ntlmssp_chk(char *desc, RPC_AUTH_NTLMSSP_CHK *chk, prs_struct *ps, int depth);
 
+/*The following definitions come from  rpc_parse/parse_samr.c  */
+
+void make_samr_q_close_hnd(SAMR_Q_CLOSE_HND *q_c, POLICY_HND *hnd);
+void samr_io_q_close_hnd(char *desc,  SAMR_Q_CLOSE_HND *q_u, prs_struct *ps, int depth);
+void samr_io_r_close_hnd(char *desc,  SAMR_R_CLOSE_HND *r_u, prs_struct *ps, int depth);
+void make_samr_q_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
+                               POLICY_HND *connect_pol, uint32 rid,
+                               DOM_SID *sid);
+void samr_io_q_open_domain(char *desc,  SAMR_Q_OPEN_DOMAIN *q_u, prs_struct *ps, int depth);
+void samr_io_r_open_domain(char *desc,  SAMR_R_OPEN_DOMAIN *r_u, prs_struct *ps, int depth);
+void make_samr_q_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u, POLICY_HND *user_pol);
+void samr_io_q_unknown_2c(char *desc,  SAMR_Q_UNKNOWN_2C *q_u, prs_struct *ps, int depth);
+void make_samr_r_unknown_2c(SAMR_R_UNKNOWN_2C *q_u, uint32 status);
+void samr_io_r_unknown_2c(char *desc,  SAMR_R_UNKNOWN_2C *r_u, prs_struct *ps, int depth);
+void make_samr_q_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
+                               POLICY_HND *user_pol, uint16 switch_value);
+void samr_io_q_unknown_3(char *desc,  SAMR_Q_UNKNOWN_3 *q_u, prs_struct *ps, int depth);
+void make_samr_q_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
+                               POLICY_HND *domain_pol, uint16 switch_value);
+void samr_io_q_query_dom_info(char *desc,  SAMR_Q_QUERY_DOMAIN_INFO *q_u, prs_struct *ps, int depth);
+void make_unk_info2(SAM_UNK_INFO_2 *u_2, char *domain, char *server);
+void sam_io_unk_info2(char *desc, SAM_UNK_INFO_2 *u_2, prs_struct *ps, int depth);
+void make_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO *r_u, 
+                               uint16 switch_value, SAM_UNK_CTR *ctr,
+                               uint32 status);
+void samr_io_r_query_dom_info(char *desc, SAMR_R_QUERY_DOMAIN_INFO *r_u, prs_struct *ps, int depth);
+void make_dom_sid3(DOM_SID3 *sid3, uint16 unk_0, uint16 unk_1, DOM_SID *sid);
+void make_samr_r_unknown_3(SAMR_R_UNKNOWN_3 *r_u,
+                               uint16 unknown_2, uint16 unknown_3,
+                               uint32 unknown_4, uint16 unknown_6, uint16 unknown_7,
+                               int num_sid3s, DOM_SID3 sid3[MAX_SAM_SIDS],
+                               uint32 status);
+void samr_io_r_unknown_3(char *desc,  SAMR_R_UNKNOWN_3 *r_u, prs_struct *ps, int depth);
+void make_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_e, POLICY_HND *pol,
+                               uint16 req_num_entries, uint16 unk_0,
+                               uint16 acb_mask, uint16 unk_1, uint32 size);
+void samr_io_q_enum_dom_users(char *desc,  SAMR_Q_ENUM_DOM_USERS *q_e, prs_struct *ps, int depth);
+void make_samr_r_enum_dom_users(SAMR_R_ENUM_DOM_USERS *r_u,
+               uint16 total_num_entries, uint16 unk_0,
+               uint32 num_sam_entries, SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], uint32 status);
+void samr_io_r_enum_dom_users(char *desc,  SAMR_R_ENUM_DOM_USERS *r_u, prs_struct *ps, int depth);
+void make_samr_q_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_e, POLICY_HND *pol, uint32 size);
+void samr_io_q_enum_dom_aliases(char *desc,  SAMR_Q_ENUM_DOM_ALIASES *q_e, prs_struct *ps, int depth);
+void make_samr_r_enum_dom_aliases(SAMR_R_ENUM_DOM_ALIASES *r_u,
+               uint32 num_sam_entries, SAM_USER_INFO_21 grps[MAX_SAM_ENTRIES],
+               uint32 status);
+void samr_io_r_enum_dom_aliases(char *desc,  SAMR_R_ENUM_DOM_ALIASES *r_u, prs_struct *ps, int depth);
+void make_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_e, POLICY_HND *pol,
+                               uint16 switch_level, uint32 start_idx, uint32 size);
+void samr_io_q_query_dispinfo(char *desc,  SAMR_Q_QUERY_DISPINFO *q_e, prs_struct *ps, int depth);
+void make_sam_info_2(SAM_INFO_2 *sam, uint32 acb_mask,
+               uint32 start_idx, uint32 num_sam_entries,
+               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]);
+void make_sam_info_1(SAM_INFO_1 *sam, uint32 acb_mask,
+               uint32 start_idx, uint32 num_sam_entries,
+               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]);
+void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u,
+               uint16 switch_level, SAM_INFO_CTR *ctr, uint32 status);
+void samr_io_r_query_dispinfo(char *desc,  SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth);
+void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol,
+                               uint16 switch_level, uint32 start_idx, uint32 size);
+void samr_io_q_enum_dom_groups(char *desc,  SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth);
+void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u,
+               uint32 start_idx, uint32 num_sam_entries,
+               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES],
+               uint32 status);
+void samr_io_r_enum_dom_groups(char *desc,  SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth);
+void make_samr_q_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_e,
+                               POLICY_HND *pol,
+                               uint16 switch_level);
+void samr_io_q_query_aliasinfo(char *desc,  SAMR_Q_QUERY_ALIASINFO *q_e, prs_struct *ps, int depth);
+void make_samr_r_query_aliasinfo(SAMR_R_QUERY_ALIASINFO *r_u,
+               uint16 switch_value, char *acct_desc,
+               uint32 status);
+void samr_io_r_query_aliasinfo(char *desc,  SAMR_R_QUERY_ALIASINFO *r_u, prs_struct *ps, int depth);
+void samr_io_q_lookup_ids(char *desc,  SAMR_Q_LOOKUP_IDS *q_u, prs_struct *ps, int depth);
+void make_samr_r_lookup_ids(SAMR_R_LOOKUP_IDS *r_u,
+               uint32 num_rids, uint32 *rid, uint32 status);
+void samr_io_r_lookup_ids(char *desc,  SAMR_R_LOOKUP_IDS *r_u, prs_struct *ps, int depth);
+void samr_io_q_lookup_names(char *desc,  SAMR_Q_LOOKUP_NAMES *q_u, prs_struct *ps, int depth);
+void make_samr_r_lookup_names(SAMR_R_LOOKUP_NAMES *r_u,
+               uint32 num_rids, uint32 *rid, uint32 status);
+void samr_io_r_lookup_names(char *desc,  SAMR_R_LOOKUP_NAMES *r_u, prs_struct *ps, int depth);
+void samr_io_q_unknown_12(char *desc,  SAMR_Q_UNKNOWN_12 *q_u, prs_struct *ps, int depth);
+void make_samr_r_unknown_12(SAMR_R_UNKNOWN_12 *r_u,
+               uint32 num_aliases, fstring *als_name, uint32 *num_als_usrs,
+               uint32 status);
+void samr_io_r_unknown_12(char *desc,  SAMR_R_UNKNOWN_12 *r_u, prs_struct *ps, int depth);
+void make_samr_q_open_user(SAMR_Q_OPEN_USER *q_u,
+                               POLICY_HND *pol,
+                               uint32 unk_0, uint32 rid);
+void samr_io_q_open_user(char *desc,  SAMR_Q_OPEN_USER *q_u, prs_struct *ps, int depth);
+void samr_io_r_open_user(char *desc,  SAMR_R_OPEN_USER *r_u, prs_struct *ps, int depth);
+void make_samr_q_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
+                               POLICY_HND *hnd);
+void samr_io_q_query_usergroups(char *desc,  SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *ps, int depth);
+void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u,
+               uint32 num_gids, DOM_GID *gid, uint32 status);
+void samr_io_r_query_usergroups(char *desc,  SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth);
+void make_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
+                               POLICY_HND *hnd, uint16 switch_value);
+void samr_io_q_query_userinfo(char *desc,  SAMR_Q_QUERY_USERINFO *q_u, prs_struct *ps, int depth);
+void make_sam_user_info10(SAM_USER_INFO_10 *usr,
+                               uint32 acb_info);
+void sam_io_user_info10(char *desc,  SAM_USER_INFO_10 *usr, prs_struct *ps, int depth);
+void make_sam_user_info11(SAM_USER_INFO_11 *usr,
+                               NTTIME *expiry,
+                               char *mach_acct,
+                               uint32 rid_user,
+                               uint32 rid_group,
+                               uint16 acct_ctrl);
+void sam_io_user_info11(char *desc,  SAM_USER_INFO_11 *usr, prs_struct *ps, int depth);
+void make_sam_user_info21(SAM_USER_INFO_21 *usr,
+
+       NTTIME *logon_time,
+       NTTIME *logoff_time,
+       NTTIME *kickoff_time,
+       NTTIME *pass_last_set_time,
+       NTTIME *pass_can_change_time,
+       NTTIME *pass_must_change_time,
+
+       char *user_name,
+       char *full_name,
+       char *home_dir,
+       char *dir_drive,
+       char *logon_script,
+       char *profile_path,
+       char *description,
+       char *workstations,
+       char *unknown_str,
+       char *munged_dial,
+
+       uint32 user_rid,
+       uint32 group_rid,
+       uint16 acb_info, 
+
+       uint32 unknown_3,
+       uint16 logon_divs,
+       LOGON_HRS *hrs,
+       uint32 unknown_5,
+       uint32 unknown_6);
+void make_samr_r_query_userinfo(SAMR_R_QUERY_USERINFO *r_u,
+                               uint16 switch_value, void *info, uint32 status);
+void samr_io_r_query_userinfo(char *desc,  SAMR_R_QUERY_USERINFO *r_u, prs_struct *ps, int depth);
+void samr_io_q_unknown_32(char *desc,  SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth);
+void samr_io_r_unknown_32(char *desc,  SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth);
+void make_samr_q_connect(SAMR_Q_CONNECT *q_u,
+                               char *srv_name, uint32 unknown_0);
+void samr_io_q_connect(char *desc,  SAMR_Q_CONNECT *q_u, prs_struct *ps, int depth);
+void samr_io_r_connect(char *desc,  SAMR_R_CONNECT *r_u, prs_struct *ps, int depth);
+void make_samr_q_connect_anon(SAMR_Q_CONNECT_ANON *q_u);
+void samr_io_q_connect_anon(char *desc,  SAMR_Q_CONNECT_ANON *q_u, prs_struct *ps, int depth);
+void samr_io_r_connect_anon(char *desc,  SAMR_R_CONNECT_ANON *r_u, prs_struct *ps, int depth);
+void make_samr_q_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
+                               uint32 unknown_0, uint32 rid);
+void samr_io_q_open_alias(char *desc,  SAMR_Q_OPEN_ALIAS *q_u, prs_struct *ps, int depth);
+void samr_io_r_open_alias(char *desc,  SAMR_R_OPEN_ALIAS *r_u, prs_struct *ps, int depth);
+void make_samr_q_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
+               POLICY_HND *pol, uint32 rid,
+               uint32 num_gids, uint32 *gid);
+void make_samr_q_unknown_21(SAMR_Q_UNKNOWN_21 *q_c,
+                               POLICY_HND *hnd, uint16 unk_1, uint16 unk_2);
+void make_samr_q_unknown_13(SAMR_Q_UNKNOWN_13 *q_c,
+                               POLICY_HND *hnd, uint16 unk_1, uint16 unk_2);
+void make_samr_q_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, char *srv_name);
+void samr_io_q_unknown_38(char *desc,  SAMR_Q_UNKNOWN_38 *q_u, prs_struct *ps, int depth);
+void make_samr_r_unknown_38(SAMR_R_UNKNOWN_38 *r_u);
+void samr_io_r_unknown_38(char *desc,  SAMR_R_UNKNOWN_38 *r_u, prs_struct *ps, int depth);
+void make_enc_passwd(SAMR_ENC_PASSWD *pwd, char pass[512]);
+void samr_io_enc_passwd(char *desc, SAMR_ENC_PASSWD *pwd, prs_struct *ps, int depth);
+void make_enc_hash(SAMR_ENC_HASH *hsh, uchar hash[16]);
+void samr_io_enc_hash(char *desc, SAMR_ENC_HASH *hsh, prs_struct *ps, int depth);
+void make_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
+                               char *dest_host, char *user_name,
+                               char nt_newpass[516], uchar nt_oldhash[16],
+                               char lm_newpass[516], uchar lm_oldhash[16]);
+void samr_io_q_chgpasswd_user(char *desc, SAMR_Q_CHGPASSWD_USER *q_u, prs_struct *ps, int depth);
+void make_samr_r_chgpasswd_user(SAMR_R_CHGPASSWD_USER *r_u, uint32 status);
+void samr_io_r_chgpasswd_user(char *desc, SAMR_R_CHGPASSWD_USER *r_u, prs_struct *ps, int depth);
+
 /*The following definitions come from  rpc_parse/parse_sec.c  */
 
 void init_sec_access(SEC_ACCESS *t, uint32 mask);
@@ -1630,6 +2012,44 @@ void make_srv_q_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n,
                                ENUM_HND *hnd);
 void srv_io_q_net_share_enum(char *desc,  SRV_Q_NET_SHARE_ENUM *q_n, prs_struct *ps, int depth);
 void srv_io_r_net_share_enum(char *desc,  SRV_R_NET_SHARE_ENUM *r_n, prs_struct *ps, int depth);
+void make_srv_sess_info0_str(SESS_INFO_0_STR *ss0, char *name);
+void make_srv_sess_info0(SESS_INFO_0 *ss0, char *name);
+void make_srv_sess_info1_str(SESS_INFO_1_STR *ss1, char *name, char *user);
+void make_srv_sess_info1(SESS_INFO_1 *ss1, 
+                               char *name, char *user,
+                               uint32 num_opens, uint32 open_time, uint32 idle_time,
+                               uint32 user_flags);
+void make_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, 
+                               char *srv_name, char *qual_name,
+                               uint32 sess_level, SRV_SESS_INFO_CTR *ctr,
+                               uint32 preferred_len,
+                               ENUM_HND *hnd);
+void srv_io_q_net_sess_enum(char *desc,  SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth);
+void srv_io_r_net_sess_enum(char *desc,  SRV_R_NET_SESS_ENUM *r_n, prs_struct *ps, int depth);
+void make_srv_conn_info0(CONN_INFO_0 *ss0, uint32 id);
+void make_srv_conn_info1_str(CONN_INFO_1_STR *ss1, char *usr_name, char *net_name);
+void make_srv_conn_info1(CONN_INFO_1 *ss1, 
+                               uint32 id, uint32 type,
+                               uint32 num_opens, uint32 num_users, uint32 open_time,
+                               char *usr_name, char *net_name);
+void make_srv_q_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n, 
+                               char *srv_name, char *qual_name,
+                               uint32 conn_level, SRV_CONN_INFO_CTR *ctr,
+                               uint32 preferred_len,
+                               ENUM_HND *hnd);
+void srv_io_q_net_conn_enum(char *desc,  SRV_Q_NET_CONN_ENUM *q_n, prs_struct *ps, int depth);
+void srv_io_r_net_conn_enum(char *desc,  SRV_R_NET_CONN_ENUM *r_n, prs_struct *ps, int depth);
+void make_srv_file_info3_str(FILE_INFO_3_STR *fi3, char *user_name, char *path_name);
+void make_srv_file_info3(FILE_INFO_3 *fl3,
+                               uint32 id, uint32 perms, uint32 num_locks,
+                               char *path_name, char *user_name);
+void make_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, 
+                               char *srv_name, char *qual_name,
+                               uint32 file_level, SRV_FILE_INFO_CTR *ctr,
+                               uint32 preferred_len,
+                               ENUM_HND *hnd);
+void srv_io_q_net_file_enum(char *desc,  SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth);
+void srv_io_r_net_file_enum(char *desc,  SRV_R_NET_FILE_ENUM *r_n, prs_struct *ps, int depth);
 void make_srv_info_101(SRV_INFO_101 *sv101, uint32 platform_id, char *name,
                                uint32 ver_major, uint32 ver_minor,
                                uint32 srv_type, char *comment);
@@ -1708,6 +2128,14 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn);
 pipes_struct *get_rpc_pipe_p(char *buf, int where);
 pipes_struct *get_rpc_pipe(int pnum);
 
+/*The following definitions come from  rpc_server/srv_reg.c  */
+
+BOOL api_reg_rpc(pipes_struct *p, prs_struct *data);
+
+/*The following definitions come from  rpc_server/srv_samr.c  */
+
+BOOL api_samr_rpc(pipes_struct *p, prs_struct *data);
+
 /*The following definitions come from  rpc_server/srv_srvsvc.c  */
 
 BOOL api_srvsvc_rpc(pipes_struct *p, prs_struct *data);
@@ -1727,6 +2155,113 @@ uint32 lookup_user_rid(char *user_name, uint32 *rid);
 
 BOOL api_wkssvc_rpc(pipes_struct *p, prs_struct *data);
 
+/*The following definitions come from  rpcclient/cmd_lsarpc.c  */
+
+void cmd_lsa_query_info(struct client_info *info);
+void cmd_lsa_lookup_sids(struct client_info *info);
+
+/*The following definitions come from  rpcclient/cmd_netlogon.c  */
+
+void cmd_netlogon_login_test(struct client_info *info);
+
+/*The following definitions come from  rpcclient/cmd_reg.c  */
+
+void cmd_reg_enum(struct client_info *info);
+void cmd_reg_query_key(struct client_info *info);
+void cmd_reg_create_val(struct client_info *info);
+void cmd_reg_delete_val(struct client_info *info);
+void cmd_reg_delete_key(struct client_info *info);
+void cmd_reg_create_key(struct client_info *info);
+void cmd_reg_test_key_sec(struct client_info *info);
+void cmd_reg_get_key_sec(struct client_info *info);
+
+/*The following definitions come from  rpcclient/cmd_samr.c  */
+
+void cmd_sam_ntchange_pwd(struct client_info *info);
+void cmd_sam_test(struct client_info *info);
+void cmd_sam_enum_users(struct client_info *info);
+void cmd_sam_query_user(struct client_info *info);
+void cmd_sam_query_groups(struct client_info *info);
+void cmd_sam_enum_aliases(struct client_info *info);
+
+/*The following definitions come from  rpcclient/cmd_srvsvc.c  */
+
+void cmd_srv_query_info(struct client_info *info);
+void cmd_srv_enum_conn(struct client_info *info);
+void cmd_srv_enum_shares(struct client_info *info);
+void cmd_srv_enum_sess(struct client_info *info);
+void cmd_srv_enum_files(struct client_info *info);
+
+/*The following definitions come from  rpcclient/cmd_wkssvc.c  */
+
+void cmd_wks_query_info(struct client_info *info);
+
+/*The following definitions come from  rpcclient/display.c  */
+
+char *get_file_mode_str(uint32 share_mode);
+char *get_file_oplock_str(uint32 op_type);
+char *get_share_type_str(uint32 type);
+char *get_server_type_str(uint32 type);
+void display_srv_info_101(FILE *out_hnd, enum action_type action,
+               SRV_INFO_101 *sv101);
+void display_srv_info_102(FILE *out_hnd, enum action_type action,SRV_INFO_102 *sv102);
+void display_srv_info_ctr(FILE *out_hnd, enum action_type action,SRV_INFO_CTR *ctr);
+void display_conn_info_0(FILE *out_hnd, enum action_type action,
+               CONN_INFO_0 *info0);
+void display_conn_info_1(FILE *out_hnd, enum action_type action,
+               CONN_INFO_1 *info1, CONN_INFO_1_STR *str1);
+void display_srv_conn_info_0_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_CONN_INFO_0 *ctr);
+void display_srv_conn_info_1_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_CONN_INFO_1 *ctr);
+void display_srv_conn_info_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_CONN_INFO_CTR *ctr);
+void display_share_info_1(FILE *out_hnd, enum action_type action,
+               SH_INFO_1 *info1, SH_INFO_1_STR *str1);
+void display_share_info_2(FILE *out_hnd, enum action_type action,
+               SH_INFO_2 *info2, SH_INFO_2_STR *str2);
+void display_srv_share_info_1_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_SHARE_INFO_1 *ctr);
+void display_srv_share_info_2_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_SHARE_INFO_2 *ctr);
+void display_srv_share_info_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_SHARE_INFO_CTR *ctr);
+void display_file_info_3(FILE *out_hnd, enum action_type action,
+               FILE_INFO_3 *info3, FILE_INFO_3_STR *str3);
+void display_srv_file_info_3_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_FILE_INFO_3 *ctr);
+void display_srv_file_info_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_FILE_INFO_CTR *ctr);
+void display_server(FILE *out_hnd, enum action_type action,
+                               char *sname, uint32 type, char *comment);
+void display_share(FILE *out_hnd, enum action_type action,
+                               char *sname, uint32 type, char *comment);
+void display_share2(FILE *out_hnd, enum action_type action,
+                               char *sname, uint32 type, char *comment,
+                               uint32 perms, uint32 max_uses, uint32 num_uses,
+                               char *path, char *passwd);
+void display_name(FILE *out_hnd, enum action_type action,
+                               char *sname);
+void display_group_rid_info(FILE *out_hnd, enum action_type action,
+                               uint32 num_gids, DOM_GID *gid);
+void display_alias_name_info(FILE *out_hnd, enum action_type action,
+                               uint32 num_aliases, fstring *alias_name, uint32 *num_als_usrs);
+void display_sam_user_info_21(FILE *out_hnd, enum action_type action, SAM_USER_INFO_21 *usr);
+char *get_sec_mask_str(uint32 type);
+void display_sec_access(FILE *out_hnd, enum action_type action, SEC_ACCESS *info);
+void display_sec_ace(FILE *out_hnd, enum action_type action, SEC_ACE *ace);
+void display_sec_acl(FILE *out_hnd, enum action_type action, SEC_ACL *sec_acl);
+void display_sec_desc(FILE *out_hnd, enum action_type action, SEC_DESC *sec);
+char *get_reg_val_type_str(uint32 type);
+void display_reg_value_info(FILE *out_hnd, enum action_type action,
+                               char *val_name, uint32 val_type, BUFFER2 *value);
+void display_reg_key_info(FILE *out_hnd, enum action_type action,
+                               char *key_name, time_t key_mod_time);
+
+/*The following definitions come from  rpcclient/rpcclient.c  */
+
+void rpcclient_init(void);
+
 /*The following definitions come from  smbd/blocking.c  */
 
 BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num);
index 8b443e15d35921b01de1504b9f3c428fc8f0b386..776605258884e379efb485ddb0b2e27dfb7e77d5 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+#ifndef _RPC_REG_H /* _RPC_REG_H */
+#define _RPC_REG_H 
+
+
+/* winreg pipe defines */
+#define REG_OPEN_HKLM       0x02
+#define REG_OPEN_HKU        0x04
+#define REG_FLUSH_KEY       0x0B
+#define REG_UNK_1A          0x1a
+#define REG_QUERY_KEY       0x10
+#define REG_ENUM_KEY        0x09
+#define REG_CREATE_KEY      0x06
+#define REG_DELETE_KEY      0x07
+#define REG_DELETE_VALUE    0x08
+#define REG_CREATE_VALUE    0x16
+#define REG_GET_KEY_SEC     0x0c
+#define REG_SET_KEY_SEC     0x15
+#define REG_ENUM_VALUE      0x0a
+#define REG_OPEN_ENTRY      0x0f
+#define REG_INFO            0x11
+#define REG_CLOSE           0x05
+
+#define HKEY_LOCAL_MACHINE 0x80000000
+#define HKEY_USERS         0x80000003
+
+/* REG_Q_OPEN_HKLM   */
+typedef struct q_reg_open_policy_info
+{
+       uint32 ptr;
+       uint16 unknown_0; /* 0xE084      - 16 bit unknown */
+       uint16 unknown_1; /* random.  changes */
+       uint32 level;     /* 0x0000 0002 - 32 bit unknown */
+
+} REG_Q_OPEN_HKLM  ;
+
+/* REG_R_OPEN_HKLM   */
+typedef struct r_reg_open_policy_info
+{
+       POLICY_HND pol;       /* policy handle */
+       uint32 status;         /* return status */
+
+} REG_R_OPEN_HKLM;
+
+
+/* REG_Q_OPEN_HKU */
+typedef struct q_reg_open_unk4_info
+{
+       uint32 ptr;
+       uint16 unknown_0; /* 0xE084      - 16 bit unknown */
+       uint16 unknown_1; /* random.  changes */
+       uint32 level;     /* 0x0000 0002 - 32 bit unknown */
+
+} REG_Q_OPEN_HKU;
+
+/* REG_R_OPEN_HKU */
+typedef struct r_reg_open_unk4_info
+{
+       POLICY_HND pol;       /* policy handle */
+       uint32 status;         /* return status */
+
+} REG_R_OPEN_HKU;
+
+
+/* REG_Q_FLUSH_KEY */
+typedef struct q_reg_open_flush_key_info
+{
+       POLICY_HND pol;       /* policy handle */
+
+} REG_Q_FLUSH_KEY;
+
+/* REG_R_FLUSH_KEY */
+typedef struct r_reg_open_flush_key_info
+{
+       uint32 status;         /* return status */
+
+} REG_R_FLUSH_KEY;
+
+
+/* REG_Q_SET_KEY_SEC */
+typedef struct q_reg_set_key_sec_info
+{
+       POLICY_HND pol;         /* policy handle */
+
+       uint32 sec_info;       /* xxxx_SECURITY_INFORMATION */
+
+       uint32 ptr;       /* pointer */
+       BUFHDR hdr_sec;    /* header for security data */
+       SEC_DESC_BUF *data;    /* security data */
+       
+} REG_Q_SET_KEY_SEC;
+
+/* REG_R_SET_KEY_SEC */
+typedef struct r_reg_set_key_sec_info
+{
+       uint32 status;
+       
+} REG_R_SET_KEY_SEC;
+
+
+/* REG_Q_GET_KEY_SEC */
+typedef struct q_reg_get_key_sec_info
+{
+       POLICY_HND pol;         /* policy handle */
+
+       uint32 sec_info;       /* xxxx_SECURITY_INFORMATION */
+
+       uint32 ptr;       /* pointer */
+       BUFHDR hdr_sec;    /* header for security data */
+       SEC_DESC_BUF *data;    /* security data */
+       
+} REG_Q_GET_KEY_SEC;
+
+/* REG_R_GET_KEY_SEC */
+typedef struct r_reg_get_key_sec_info
+{
+       uint32 sec_info;       /* xxxx_SECURITY_INFORMATION */
+
+       uint32 ptr;       /* pointer */
+       BUFHDR hdr_sec;    /* header for security data */
+       SEC_DESC_BUF *data;    /* security data */
+
+       uint32 status;
+       
+} REG_R_GET_KEY_SEC;
+
+/* REG_Q_CREATE_VALUE */
+typedef struct q_reg_create_value_info
+{
+       POLICY_HND pol;    /* policy handle */
+
+       UNIHDR hdr_name;   /* name of value */
+       UNISTR2 uni_name;
+
+       uint32 type;       /* 1 = UNISTR, 3 = BYTES, 4 = DWORD, 7 = MULTI_UNISTR */
+
+       BUFFER3 *buf_value; /* value, in byte buffer */
+
+} REG_Q_CREATE_VALUE;
+
+/* REG_R_CREATE_VALUE */
+typedef struct r_reg_create_value_info
+{ 
+       uint32 status;         /* return status */
+
+} REG_R_CREATE_VALUE;
+
+/* REG_Q_ENUM_VALUE */
+typedef struct q_reg_query_value_info
+{
+       POLICY_HND pol;    /* policy handle */
+
+       uint32 val_index;  /* index */
+
+       UNIHDR hdr_name;   /* name of value */
+       UNISTR2 uni_name;
+
+       uint32 ptr_type;   /* pointer */
+       uint32 type;       /* 1 = UNISTR, 3 = BYTES, 4 = DWORD, 7 = MULTI_UNISTR */
+
+       uint32 ptr_value;  /* pointer */
+       BUFFER2 buf_value; /* value, in byte buffer */
+
+       uint32 ptr1;       /* pointer */
+       uint32 len_value1; /* */
+
+       uint32 ptr2;       /* pointer */
+       uint32 len_value2; /* */
+
+} REG_Q_ENUM_VALUE;
+
+/* REG_R_ENUM_VALUE */
+typedef struct r_reg_enum_value_info
+{ 
+       UNIHDR hdr_name;        /* name of value */
+       UNISTR2 uni_name;
+
+       uint32 ptr_type;            /* pointer */
+       uint32 type;        /* 1 = UNISTR, 3 = BYTES, 4 = DWORD, 7 = MULTI_UNISTR */
+
+       uint32 ptr_value;       /* pointer */
+       BUFFER2 *buf_value;    /* value, in byte buffer */
+
+       uint32 ptr1;            /* pointer */
+       uint32 len_value1;       /* */
+
+       uint32 ptr2;            /* pointer */
+       uint32 len_value2;       /* */
+
+       uint32 status;         /* return status */
+
+} REG_R_ENUM_VALUE;
+
+/* REG_Q_CREATE_KEY */
+typedef struct q_reg_create_key_info
+{
+       POLICY_HND pnt_pol;       /* parent key policy handle */
+
+       UNIHDR hdr_name;
+       UNISTR2 uni_name;
+
+       UNIHDR hdr_class;
+       UNISTR2 uni_class;
+
+       uint32 reserved; /* 0x0000 0000 */
+       SEC_ACCESS sam_access; /* access rights flags, see rpc_secdes.h */
+
+       uint32 ptr1;
+       uint32 sec_info; /* xxxx_SECURITY_INFORMATION */
+
+       uint32 ptr2;       /* pointer */
+       BUFHDR hdr_sec;    /* header for security data */
+       uint32 ptr3;       /* pointer */
+       SEC_DESC_BUF *data;
+
+       uint32 unknown_2; /* 0x0000 0000 */
+
+} REG_Q_CREATE_KEY;
+
+/* REG_R_CREATE_KEY */
+typedef struct r_reg_create_key_info
+{
+       POLICY_HND key_pol;       /* policy handle */
+       uint32 unknown; /* 0x0000 0000 */
+
+       uint32 status;         /* return status */
+
+} REG_R_CREATE_KEY;
+
+/* REG_Q_DELETE_KEY */
+typedef struct q_reg_delete_key_info
+{
+       POLICY_HND pnt_pol;       /* parent key policy handle */
+
+       UNIHDR hdr_name;
+       UNISTR2 uni_name;
+} REG_Q_DELETE_KEY;
+
+/* REG_R_DELETE_KEY */
+typedef struct r_reg_delete_key_info
+{
+       POLICY_HND key_pol;       /* policy handle */
+
+       uint32 status;         /* return status */
+
+} REG_R_DELETE_KEY;
+
+/* REG_Q_DELETE_VALUE */
+typedef struct q_reg_delete_val_info
+{
+       POLICY_HND pnt_pol;       /* parent key policy handle */
+
+       UNIHDR hdr_name;
+       UNISTR2 uni_name;
+
+} REG_Q_DELETE_VALUE;
+
+/* REG_R_DELETE_VALUE */
+typedef struct r_reg_delete_val_info
+{
+       POLICY_HND key_pol;       /* policy handle */
+
+       uint32 status;         /* return status */
+
+} REG_R_DELETE_VALUE;
+
+/* REG_Q_QUERY_KEY */
+typedef struct q_reg_query_info
+{
+       POLICY_HND pol;       /* policy handle */
+       UNIHDR hdr_class;
+       UNISTR2 uni_class;
+
+} REG_Q_QUERY_KEY;
+
+/* REG_R_QUERY_KEY */
+typedef struct r_reg_query_key_info
+{
+       UNIHDR hdr_class;
+       UNISTR2 uni_class;
+
+       uint32 num_subkeys;
+       uint32 max_subkeylen;
+       uint32 max_subkeysize; /* 0x0000 0000 */
+       uint32 num_values;
+       uint32 max_valnamelen;
+       uint32 max_valbufsize; 
+       uint32 sec_desc; /* 0x0000 0078 */
+       NTTIME mod_time;  /* modified time */
+
+       uint32 status;         /* return status */
+
+} REG_R_QUERY_KEY;
+
+
+/* REG_Q_UNK_1A */
+typedef struct q_reg_unk_1a_info
+{
+       POLICY_HND pol;       /* policy handle */
+
+} REG_Q_UNK_1A;
+
+/* REG_R_UNK_1A */
+typedef struct r_reg_unk_1a_info
+{
+       uint32 unknown;         /* 0x0500 0000 */
+       uint32 status;         /* return status */
+
+} REG_R_UNK_1A;
+
+
+/* REG_Q_CLOSE */
+typedef struct reg_q_close_info
+{
+       POLICY_HND pol; /* policy handle */
+
+} REG_Q_CLOSE;
+
+/* REG_R_CLOSE */
+typedef struct reg_r_close_info
+{
+       POLICY_HND pol; /* policy handle.  should be all zeros. */
+
+       uint32 status; /* return code */
+
+} REG_R_CLOSE;
+
+
+/* REG_Q_ENUM_KEY */
+typedef struct q_reg_enum_value_info
+{
+       POLICY_HND pol;         /* policy handle */
+
+       uint32 key_index;       
+
+       uint16 key_name_len;    /* 0x0000 */
+       uint16 unknown_1;       /* 0x0414 */
+
+       uint32 ptr1;            /* pointer */
+       uint32 unknown_2;       /* 0x0000 020A */
+       uint8  pad1[8];         /* padding - zeros */
+
+       uint32 ptr2;            /* pointer */
+       uint8  pad2[8];         /* padding - zeros */
+
+       uint32 ptr3;            /* pointer */
+       NTTIME time;            /* current time? */
+
+} REG_Q_ENUM_KEY;
+
+/* REG_R_ENUM_KEY */
+typedef struct r_reg_enum_key_info
+{ 
+       uint16 key_name_len;    /* number of bytes in key name */
+       uint16 unknown_1;       /* 0x0414 - matches with query unknown_1 */
+
+       uint32 ptr1;            /* pointer */
+       uint32 unknown_2;       /* 0x0000 020A */
+       uint32 unknown_3;       /* 0x0000 0000 */
+
+       UNISTR3 key_name;
+
+       uint32 ptr2;            /* pointer */
+       uint8  pad2[8];         /* padding - zeros */
+
+       uint32 ptr3;            /* pointer */
+       NTTIME time;            /* current time? */
+
+       uint32 status;         /* return status */
+
+} REG_R_ENUM_KEY;
+
+
+/* REG_Q_INFO */
+typedef struct q_reg_info_info
+{
+       POLICY_HND pol;        /* policy handle */
+
+       UNIHDR  hdr_type;       /* unicode product type header */
+       UNISTR2 uni_type;       /* unicode product type - "ProductType" */
+
+       uint32 ptr1;            /* pointer */
+       NTTIME time;            /* current time? */
+       uint8  major_version1;  /* 0x4 - os major version? */
+       uint8  minor_version1;  /* 0x1 - os minor version? */
+       uint8  pad1[10];        /* padding - zeros */
+
+       uint32 ptr2;            /* pointer */
+       uint8  major_version2;  /* 0x4 - os major version? */
+       uint8  minor_version2;  /* 0x1 - os minor version? */
+       uint8  pad2[2];         /* padding - zeros */
+
+       uint32 ptr3;            /* pointer */
+       uint32 unknown;         /* 0x0000 0000 */
+
+} REG_Q_INFO;
+
+/* REG_R_INFO */
+typedef struct r_reg_info_info
+{ 
+       uint32 ptr1;            /* buffer pointer */
+       uint32 level;          /* 0x1 - info level? */
+
+       uint32 ptr_type;       /* pointer to o/s type */
+       BUFFER2 uni_type;      /* unicode string o/s type - "LanmanNT" */
+
+       uint32 ptr2;           /* pointer to unknown_0 */
+       uint32 unknown_0;      /* 0x12 */
+
+       uint32 ptr3;           /* pointer to unknown_1 */
+       uint32 unknown_1;      /* 0x12 */
+
+       uint32 status;         /* return status */
+
+} REG_R_INFO;
+
+
+/* REG_Q_OPEN_ENTRY */
+typedef struct q_reg_open_entry_info
+{
+       POLICY_HND pol;        /* policy handle */
+
+       UNIHDR  hdr_name;       /* unicode registry string header */
+       UNISTR2 uni_name;       /* unicode registry string name */
+
+       uint32 unknown_0;       /* 32 bit unknown - 0x0000 0000 */
+       uint32 unknown_1;       /* 32 bit unknown - 0x0200 0000 */
+
+} REG_Q_OPEN_ENTRY;
+
+
+
+/* REG_R_OPEN_ENTRY */
+typedef struct r_reg_open_entry_info
+{
+       POLICY_HND pol;       /* policy handle */
+       uint32 status;         /* return status */
+
+} REG_R_OPEN_ENTRY;
+
+
+
+#endif /* _RPC_REG_H */
+
index 8b443e15d35921b01de1504b9f3c428fc8f0b386..d45cb23388f91da8e548d3d2314dbe594d44d14f 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+#ifndef _RPC_SAMR_H /* _RPC_SAMR_H */
+#define _RPC_SAMR_H 
+
+
+#include "rpc_misc.h"
+
+
+/*******************************************************************
+ the following information comes from a QuickView on samsrv.dll,
+ and gives an idea of exactly what is needed:
+SamrAddMemberToAlias
+SamrAddMemberToGroup
+SamrAddMultipleMembersToAlias
+SamrChangePasswordUser
+x SamrCloseHandle
+x SamrConnect
+SamrCreateAliasInDomain
+SamrCreateGroupInDomain
+SamrCreateUserInDomain
+SamrDeleteAlias
+SamrDeleteGroup
+SamrDeleteUser
+x SamrEnumerateAliasesInDomain
+SamrEnumerateDomainsInSamServer
+x SamrEnumerateGroupsInDomain
+x SamrEnumerateUsersInDomain
+SamrGetUserDomainPasswordInformation
+SamrLookupDomainInSamServer
+? SamrLookupIdsInDomain
+x SamrLookupNamesInDomain
+x SamrOpenAlias
+x SamrOpenDomain
+SamrOpenGroup
+x SamrOpenUser
+x SamrQueryDisplayInformation
+x SamrQueryInformationAlias
+SamrQueryInformationDomain
+? SamrQueryInformationUser
+SamrQuerySecurityObject
+SamrRemoveMemberFromAlias
+SamrRemoveMemberFromForiegnDomain
+SamrRemoveMemberFromGroup
+SamrRemoveMultipleMembersFromAlias
+SamrSetInformationAlias
+SamrSetInformationDomain
+SamrSetInformationGroup
+SamrSetInformationUser
+SamrSetMemberAttributesOfGroup
+SamrSetSecurityObject
+SamrShutdownSamServer
+SamrTestPrivateFunctionsDomain
+SamrTestPrivateFunctionsUser
+
+********************************************************************/
+
+#define SAMR_CLOSE_HND         0x01
+#define SAMR_OPEN_DOMAIN       0x07
+#define SAMR_QUERY_DOMAIN_INFO 0x08
+#define SAMR_LOOKUP_IDS        0x10
+#define SAMR_LOOKUP_NAMES      0x11
+#define SAMR_UNKNOWN_3         0x03
+#define SAMR_QUERY_DISPINFO    0x28
+#define SAMR_OPEN_USER         0x22
+#define SAMR_QUERY_USERINFO    0x24
+#define SAMR_QUERY_USERGROUPS  0x27
+#define SAMR_UNKNOWN_12        0x12
+#define SAMR_UNKNOWN_21        0x21
+#define SAMR_UNKNOWN_2C        0x2c
+#define SAMR_UNKNOWN_32        0x32
+#define SAMR_UNKNOWN_34        0x34
+#define SAMR_CHGPASSWD_USER    0x37
+#define SAMR_UNKNOWN_38        0x38
+#define SAMR_CONNECT           0x39
+#define SAMR_CONNECT_ANON      0x00
+#define SAMR_OPEN_ALIAS        0x1b
+#define SAMR_QUERY_ALIASINFO   0x1c
+#define SAMR_ENUM_DOM_USERS    0x0d
+#define SAMR_ENUM_DOM_ALIASES  0x0f
+#define SAMR_ENUM_DOM_GROUPS   0x30
+
+
+typedef struct logon_hours_info
+{
+       uint32 len; /* normally 21 bytes */
+       uint8 hours[32];
+
+} LOGON_HRS;
+
+/* SAM_USER_INFO_21 */
+typedef struct sam_user_info_21
+{
+       NTTIME logon_time;            /* logon time */
+       NTTIME logoff_time;           /* logoff time */
+       NTTIME kickoff_time;          /* kickoff time */
+       NTTIME pass_last_set_time;    /* password last set time */
+       NTTIME pass_can_change_time;  /* password can change time */
+       NTTIME pass_must_change_time; /* password must change time */
+
+       UNIHDR hdr_user_name;    /* username unicode string header */
+       UNIHDR hdr_full_name;    /* user's full name unicode string header */
+       UNIHDR hdr_home_dir;     /* home directory unicode string header */
+       UNIHDR hdr_dir_drive;    /* home drive unicode string header */
+       UNIHDR hdr_logon_script; /* logon script unicode string header */
+       UNIHDR hdr_profile_path; /* profile path unicode string header */
+       UNIHDR hdr_acct_desc  ;  /* user description */
+       UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */
+       UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */
+       UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */
+
+       uint8 lm_pwd[16];    /* lm user passwords */
+       uint8 nt_pwd[16];    /* nt user passwords */
+
+       uint32 user_rid;      /* Primary User ID */
+       uint32 group_rid;     /* Primary Group ID */
+
+       uint16 acb_info; /* account info (ACB_xxxx bit-mask) */
+       /* uint8 pad[2] */
+
+       uint32 unknown_3; /* 0x00ff ffff */
+
+       uint16 logon_divs; /* 0x0000 00a8 which is 168 which is num hrs in a week */
+       /* uint8 pad[2] */
+       uint32 ptr_logon_hrs; /* unknown pointer */
+
+       uint32 unknown_5;     /* 0x0002 0000 */
+
+       uint8 padding1[8];
+
+       UNISTR2 uni_user_name;    /* username unicode string */
+       UNISTR2 uni_full_name;    /* user's full name unicode string */
+       UNISTR2 uni_home_dir;     /* home directory unicode string */
+       UNISTR2 uni_dir_drive;    /* home directory drive unicode string */
+       UNISTR2 uni_logon_script; /* logon script unicode string */
+       UNISTR2 uni_profile_path; /* profile path unicode string */
+       UNISTR2 uni_acct_desc  ;  /* user description unicode string */
+       UNISTR2 uni_workstations; /* login from workstations unicode string */
+       UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
+       UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */
+
+       uint32 unknown_6; /* 0x0000 04ec */
+       uint32 padding4;
+
+       LOGON_HRS logon_hrs;
+
+} SAM_USER_INFO_21;
+
+
+/* SAM_USER_INFO_11 */
+typedef struct sam_user_info_11
+{
+       uint8  padding_0[16];  /* 0 - padding 16 bytes */
+       NTTIME expiry;         /* expiry time or something? */
+       uint8  padding_1[24];  /* 0 - padding 24 bytes */
+
+       UNIHDR hdr_mach_acct;  /* unicode header for machine account */
+       uint32 padding_2;      /* 0 - padding 4 bytes */
+
+       uint32 ptr_1;          /* pointer */
+       uint8  padding_3[32];  /* 0 - padding 32 bytes */
+       uint32 padding_4;      /* 0 - padding 4 bytes */
+
+       uint32 ptr_2;          /* pointer */
+       uint32 padding_5;      /* 0 - padding 4 bytes */
+
+       uint32 ptr_3;          /* pointer */
+       uint8  padding_6[32];  /* 0 - padding 32 bytes */
+
+       uint32 rid_user;       /* user RID */
+       uint32 rid_group;      /* group RID */
+
+       uint16 acct_ctrl;      /* 0080 - ACB_XXXX */
+       uint16 unknown_3;      /* 16 bit padding */
+
+       uint16 unknown_4;      /* 0x003f      - 16 bit unknown */
+       uint16 unknown_5;      /* 0x003c      - 16 bit unknown */
+
+       uint8  padding_7[16];  /* 0 - padding 16 bytes */
+       uint32 padding_8;      /* 0 - padding 4 bytes */
+       
+       UNISTR2 uni_mach_acct; /* unicode string for machine account */
+
+       uint8  padding_9[48];  /* 0 - padding 48 bytes */
+
+} SAM_USER_INFO_11;
+
+
+/* SAM_USER_INFO_10 */
+typedef struct sam_user_info_10
+{
+       uint32 acb_info;
+
+} SAM_USER_INFO_10;
+
+
+
+/* SAMR_Q_CLOSE_HND - probably a policy handle close */
+typedef struct q_samr_close_hnd_info
+{
+    POLICY_HND pol;          /* policy handle */
+
+} SAMR_Q_CLOSE_HND;
+
+
+/* SAMR_R_CLOSE_HND - probably a policy handle close */
+typedef struct r_samr_close_hnd_info
+{
+    POLICY_HND pol;       /* policy handle */
+       uint32 status;         /* return status */
+
+} SAMR_R_CLOSE_HND;
+
+
+/****************************************************************************
+SAMR_Q_UNKNOWN_2C - a "set user info" occurs just after this
+*****************************************************************************/
+
+/* SAMR_Q_UNKNOWN_2C */
+typedef struct q_samr_unknown_2c_info
+{
+       POLICY_HND user_pol;          /* policy handle */
+
+} SAMR_Q_UNKNOWN_2C;
+
+
+/****************************************************************************
+SAMR_R_UNKNOWN_2C - a "set user info" occurs just after this
+*****************************************************************************/
+
+/* SAMR_R_UNKNOWN_2C */
+typedef struct r_samr_unknown_2c_info
+{
+       uint32 unknown_0; /* 0x0016 0000 */
+       uint32 unknown_1; /* 0x0000 0000 */
+       uint32 status; 
+
+} SAMR_R_UNKNOWN_2C;
+
+
+/****************************************************************************
+SAMR_Q_UNKNOWN_3 - info level 4.  returns SIDs.
+*****************************************************************************/
+
+/* SAMR_Q_UNKNOWN_3 - probably get domain info... */
+typedef struct q_samr_unknown_3_info
+{
+       POLICY_HND user_pol;          /* policy handle */
+       uint16 switch_value;     /* 0x0000 0004 */
+       /* uint8 pad[2] */
+
+} SAMR_Q_UNKNOWN_3;
+
+/* DOM_SID3 example:
+   0x14 0x035b 0x0002 S-1-1
+   0x18 0x07ff 0x000f S-1-5-20-DOMAIN_ALIAS_RID_ADMINS
+   0x18 0x07ff 0x000f S-1-5-20-DOMAIN_ALIAS_RID_ACCOUNT_OPS
+   0x24 0x0044 0x0002 S-1-5-21-nnn-nnn-nnn-0x03f1
+ */
+
+/* DOM_SID3 example:
+   0x24 0x0044 0x0002 S-1-5-21-nnn-nnn-nnn-0x03ee
+   0x18 0x07ff 0x000f S-1-5-20-DOMAIN_ALIAS_RID_ADMINS
+   0x14 0x035b 0x0002 S-1-1
+ */
+
+/* DOM_SID3 - security id */
+typedef struct sid_info_3
+{
+       uint16 len; /* length, bytes, including length of len :-) */
+       /* uint8  pad[2]; */
+       
+       DOM_SID sid;
+
+} DOM_SID3;
+
+
+#define MAX_SAM_SIDS 15
+
+/* SAM_SID_STUFF */
+typedef struct sid_stuff_info
+{
+       uint16 unknown_2; /* 0x0001 */
+       uint16 unknown_3; /* 0x8004 */
+
+       uint8 padding1[8];
+
+       uint32 unknown_4; /* 0x0000 0014 */
+       uint32 unknown_5; /* 0x0000 0014 */
+
+       uint16 unknown_6; /* 0x0002 */
+       uint16 unknown_7; /* 0x5800 */
+
+       uint32 num_sids;
+
+       uint16 padding2;
+
+       DOM_SID3 sid[MAX_SAM_SIDS];
+
+} SAM_SID_STUFF;
+
+/* SAMR_R_UNKNOWN_3 - probably an open */
+typedef struct r_samr_unknown_3_info
+{
+       uint32 ptr_0;
+       uint32 sid_stuff_len0;
+
+       uint32 ptr_1;
+       uint32 sid_stuff_len1;
+
+       SAM_SID_STUFF sid_stuff;
+
+       uint32 status;         /* return status */
+
+} SAMR_R_UNKNOWN_3;
+
+
+/****************************************************************************
+SAMR_Q_QUERY_DOMAIN_INFO - probably a query on domain group info.
+*****************************************************************************/
+
+/* SAMR_Q_QUERY_DOMAIN_INFO - */
+typedef struct q_samr_query_domain_info
+{
+       POLICY_HND domain_pol;   /* policy handle */
+       uint16 switch_value;     /* 0x0002 */
+
+} SAMR_Q_QUERY_DOMAIN_INFO;
+
+typedef struct sam_unkown_info_2_info
+{
+       uint32 unknown_0; /* 0x0000 0000 */
+       uint32 unknown_1; /* 0x8000 0000 */
+       uint32 unknown_2; /* 0x0000 0000 */
+
+       uint32 ptr_0;     /* pointer to unknown structure */
+       UNIHDR hdr_domain; /* domain name unicode header */
+       UNIHDR hdr_server; /* server name unicode header */
+
+       /* put all the data in here, at the moment, including what the above
+          pointer is referring to
+        */
+
+       uint32 seq_num; /* some sort of incrementing sequence number? */
+       uint32 unknown_3; /* 0x0000 0000 */
+       
+       uint32 unknown_4; /* 0x0000 0001 */
+       uint32 unknown_5; /* 0x0000 0003 */
+       uint32 unknown_6; /* 0x0000 0001 */
+       uint32 num_domain_usrs; /* number of users in domain */
+       uint32 num_domain_grps; /* number of domain groups in domain */
+       uint32 num_local_grps; /* number of local groups in domain */
+
+       uint8 padding[12]; /* 12 bytes zeros */
+
+       UNISTR2 uni_domain; /* domain name unicode string */
+       UNISTR2 uni_server; /* server name unicode string */
+
+} SAM_UNK_INFO_2;
+
+
+typedef struct sam_unknown_ctr_info
+{
+       union
+       {
+               SAM_UNK_INFO_2 inf2;
+
+       } info;
+
+} SAM_UNK_CTR;
+
+
+/* SAMR_R_QUERY_DOMAIN_INFO - */
+typedef struct r_samr_query_domain_info
+{
+       uint32 ptr_0;
+       uint16 switch_value; /* same as in query */
+
+       SAM_UNK_CTR *ctr;
+
+       uint32 status;         /* return status */
+
+} SAMR_R_QUERY_DOMAIN_INFO;
+
+
+/****************************************************************************
+SAMR_Q_OPEN_DOMAIN - unknown_0 values seen associated with SIDs:
+
+0x0000 03f1 and a specific   domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0
+0x0000 0200 and a specific   domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0
+*****************************************************************************/
+
+/* SAMR_Q_OPEN_DOMAIN */
+typedef struct q_samr_open_domain_info
+{
+       POLICY_HND connect_pol;   /* policy handle */
+       uint32 rid;               /* 0x2000 0000; 0x0000 0211; 0x0000 0280; 0x0000 0200 - a RID? */
+       DOM_SID2 dom_sid;         /* domain SID */
+
+} SAMR_Q_OPEN_DOMAIN;
+
+
+/* SAMR_R_OPEN_DOMAIN - probably an open */
+typedef struct r_samr_open_domain_info
+{
+       POLICY_HND domain_pol; /* policy handle associated with the SID */
+       uint32 status;         /* return status */
+
+} SAMR_R_OPEN_DOMAIN;
+
+
+#define MAX_SAM_ENTRIES 250
+
+typedef struct samr_entry_info
+{
+       uint32 rid;
+       UNIHDR hdr_name;
+
+} SAM_ENTRY;
+
+/* SAMR_Q_ENUM_DOM_USERS - SAM rids and names */
+typedef struct q_samr_enum_dom_users_info
+{
+       POLICY_HND pol;          /* policy handle */
+
+       uint16 req_num_entries;   /* number of values (0 indicates unlimited?) */
+       uint16 unknown_0;         /* enumeration context? */
+       uint16 acb_mask;          /* 0x0000 indicates all */
+       uint16 unknown_1;         /* 0x0000 */
+
+       uint32 max_size;              /* 0x0000 ffff */
+
+} SAMR_Q_ENUM_DOM_USERS;
+
+
+/* SAMR_R_ENUM_DOM_USERS - SAM rids and names */
+typedef struct r_samr_enum_dom_users_info
+{
+       uint16 total_num_entries;  /* number of entries that match without the acb mask */
+       uint16 unknown_0;          /* same as unknown_0 (enum context?) in request */
+       uint32 ptr_entries1;       /* actual number of entries to follow, having masked some out */
+
+       uint32 num_entries2;
+       uint32 ptr_entries2;
+
+       uint32 num_entries3;
+
+       SAM_ENTRY sam[MAX_SAM_ENTRIES];
+       UNISTR2 uni_acct_name[MAX_SAM_ENTRIES];
+
+       uint32 num_entries4;
+
+       uint32 status;
+
+} SAMR_R_ENUM_DOM_USERS;
+
+
+typedef struct samr_entry_info3
+{
+       uint32 grp_idx;
+
+       uint32 rid_grp;
+       uint32 attr;
+
+       UNIHDR hdr_grp_name;
+       UNIHDR hdr_grp_desc;
+
+} SAM_ENTRY3;
+
+typedef struct samr_str_entry_info3
+{
+       UNISTR2 uni_grp_name;
+       UNISTR2 uni_grp_desc;
+
+} SAM_STR3;
+
+/* SAMR_Q_ENUM_DOM_GROUPS - SAM rids and names */
+typedef struct q_samr_enum_dom_groups_info
+{
+       POLICY_HND pol;          /* policy handle */
+
+       /* these are possibly an enumeration context handle... */
+       uint16 switch_level;      /* 0x0003 */
+       uint16 unknown_0;         /* 0x0000 */
+       uint32 start_idx;       /* presumably the start enumeration index */
+       uint32 unknown_1;       /* 0x0000 07d0 */
+
+       uint32 max_size;        /* 0x0000 7fff */
+
+} SAMR_Q_ENUM_DOM_GROUPS;
+
+
+/* SAMR_R_ENUM_DOM_GROUPS - SAM rids and names */
+typedef struct r_samr_enum_dom_groups_info
+{
+       uint32 unknown_0;        /* 0x0000 0492 or 0x0000 00be */
+       uint32 unknown_1;        /* 0x0000 049a or 0x0000 00be */
+       uint32 switch_level;     /* 0x0000 0003 */
+
+       uint32 num_entries;
+       uint32 ptr_entries;
+
+       uint32 num_entries2;
+
+       SAM_ENTRY3 sam[MAX_SAM_ENTRIES];
+       SAM_STR3   str[MAX_SAM_ENTRIES];
+
+       uint32 status;
+
+} SAMR_R_ENUM_DOM_GROUPS;
+
+
+
+/* SAMR_Q_ENUM_DOM_ALIASES - SAM rids and names */
+typedef struct q_samr_enum_dom_aliases_info
+{
+       POLICY_HND pol;          /* policy handle */
+
+       /* this is possibly an enumeration context handle... */
+       uint32 unknown_0;         /* 0x0000 0000 */
+
+       uint32 max_size;              /* 0x0000 ffff */
+
+} SAMR_Q_ENUM_DOM_ALIASES;
+
+/* SAMR_R_ENUM_DOM_ALIASES - SAM rids and names */
+typedef struct r_samr_enum_dom_aliases_info
+{
+       uint32 num_entries;
+       uint32 ptr_entries;
+
+       uint32 num_entries2;
+       uint32 ptr_entries2;
+
+       uint32 num_entries3;
+
+       SAM_ENTRY sam[MAX_SAM_ENTRIES];
+       UNISTR2 uni_grp_name[MAX_SAM_ENTRIES];
+
+       uint32 num_entries4;
+
+       uint32 status;
+
+} SAMR_R_ENUM_DOM_ALIASES;
+
+
+
+/* SAMR_Q_QUERY_DISPINFO - SAM rids, names and descriptions */
+typedef struct q_samr_query_disp_info
+{
+       POLICY_HND pol;        /* policy handle */
+
+       uint16 switch_level;    /* 0x0001 and 0x0002 seen */
+       uint16 unknown_0;       /* 0x0000 and 0x2000 seen */
+       uint32 start_idx;       /* presumably the start enumeration index */
+       uint32 unknown_1;       /* 0x0000 07d0, 0x0000 0400 and 0x0000 0200 seen */
+
+       uint32 max_size;        /* 0x0000 7fff, 0x0000 7ffe and 0x0000 3fff seen*/
+
+} SAMR_Q_QUERY_DISPINFO;
+
+typedef struct samr_entry_info1
+{
+       uint32 user_idx;
+
+       uint32 rid_user;
+       uint16 acb_info;
+       uint16 pad;
+
+       UNIHDR hdr_acct_name;
+       UNIHDR hdr_user_name;
+       UNIHDR hdr_user_desc;
+
+} SAM_ENTRY1;
+
+typedef struct samr_str_entry_info1
+{
+       UNISTR2 uni_acct_name;
+       UNISTR2 uni_full_name;
+       UNISTR2 uni_acct_desc;
+
+} SAM_STR1;
+
+typedef struct sam_entry_info_1
+{
+       uint32 num_entries;
+       uint32 ptr_entries;
+       uint32 num_entries2;
+
+       SAM_ENTRY1 sam[MAX_SAM_ENTRIES];
+       SAM_STR1   str[MAX_SAM_ENTRIES];
+
+
+} SAM_INFO_1;
+
+typedef struct samr_entry_info2
+{
+       uint32 user_idx;
+
+       uint32 rid_user;
+       uint16 acb_info;
+       uint16 pad;
+
+       UNIHDR hdr_srv_name;
+       UNIHDR hdr_srv_desc;
+
+} SAM_ENTRY2;
+
+typedef struct samr_str_entry_info2
+{
+       UNISTR2 uni_srv_name;
+       UNISTR2 uni_srv_desc;
+
+} SAM_STR2;
+
+typedef struct sam_entry_info_2
+{
+       uint32 num_entries;
+       uint32 ptr_entries;
+       uint32 num_entries2;
+
+       SAM_ENTRY2 sam[MAX_SAM_ENTRIES];
+       SAM_STR2   str[MAX_SAM_ENTRIES];
+
+} SAM_INFO_2;
+
+typedef struct sam_info_ctr_info
+{
+       union
+       {
+               SAM_INFO_1 *info1; /* server info */
+               SAM_INFO_2 *info2; /* user info */
+               void       *info; /* allows assignment without typecasting, */
+
+       } sam;
+
+} SAM_INFO_CTR;
+
+/* SAMR_R_QUERY_DISPINFO - SAM rids, names and descriptions */
+typedef struct r_samr_query_dispinfo_info
+{
+       uint32 unknown_0;        /* container length? 0x0000 0492 or 0x0000 00be */
+       uint32 unknown_1;        /* container length? 0x0000 049a or 0x0000 00be */
+       uint16 switch_level;     /* 0x0001 or 0x0002 */
+       /*uint8 pad[2] */
+
+       SAM_INFO_CTR *ctr;
+
+       uint32 status;
+
+} SAMR_R_QUERY_DISPINFO;
+
+
+
+/* SAMR_Q_QUERY_ALIASINFO - SAM Alias Info */
+typedef struct q_samr_enum_alias_info
+{
+       POLICY_HND pol;        /* policy handle */
+
+       uint16 switch_level;    /* 0x0003 seen */
+
+} SAMR_Q_QUERY_ALIASINFO;
+
+typedef struct samr_alias_info3
+{
+       UNIHDR hdr_acct_desc;
+       UNISTR2 uni_acct_desc;
+
+} ALIAS_INFO3;
+
+/* SAMR_R_QUERY_ALIASINFO - SAM rids, names and descriptions */
+typedef struct r_samr_query_aliasinfo_info
+{
+       uint32 ptr;        
+       uint16 switch_value;     /* 0x0003 */
+       /* uint8[2] padding */
+
+       union
+       {
+               ALIAS_INFO3 info3;
+
+       } alias;
+
+       uint32 status;
+
+} SAMR_R_QUERY_ALIASINFO;
+
+
+/* SAMR_Q_QUERY_USERGROUPS - */
+typedef struct q_samr_query_usergroup_info
+{
+       POLICY_HND pol;          /* policy handle associated with unknown id */
+
+} SAMR_Q_QUERY_USERGROUPS;
+
+/* SAMR_R_QUERY_USERGROUPS - probably a get sam info */
+typedef struct r_samr_query_usergroup_info
+{
+       uint32 ptr_0;            /* pointer */
+       uint32 num_entries;      /* number of RID groups */
+       uint32 ptr_1;            /* pointer */
+       uint32 num_entries2;     /* number of RID groups */
+
+       DOM_GID *gid; /* group info */
+
+       uint32 status;         /* return status */
+
+} SAMR_R_QUERY_USERGROUPS;
+
+
+/* SAMR_Q_QUERY_USERINFO - probably a get sam info */
+typedef struct q_samr_query_user_info
+{
+       POLICY_HND pol;          /* policy handle associated with unknown id */
+       uint16 switch_value;         /* 0x0015, 0x0011 or 0x0010 - 16 bit unknown */
+
+} SAMR_Q_QUERY_USERINFO;
+
+/* SAMR_R_QUERY_USERINFO - probably a get sam info */
+typedef struct r_samr_query_user_info
+{
+       uint32 ptr;            /* pointer */
+       uint16 switch_value;      /* 0x0015, 0x0011 or 0x0010 - same as in query */
+       /* uint8[2] padding. */
+
+       union
+       {
+               SAM_USER_INFO_10 *id10; /* auth-level 0x10 */
+               SAM_USER_INFO_11 *id11; /* auth-level 0x11 */
+               SAM_USER_INFO_21 *id21; /* auth-level 21 */
+               void* id; /* to make typecasting easy */
+
+       } info;
+
+       uint32 status;         /* return status */
+
+} SAMR_R_QUERY_USERINFO;
+
+
+/****************************************************************************
+SAMR_Q_LOOKUP_IDS - do a conversion from name to RID.
+
+the policy handle allocated by an "samr open secret" call is associated
+with a SID.  this policy handle is what is queried here, *not* the SID
+itself.  the response to the lookup rids is relative to this SID.
+*****************************************************************************/
+/* SAMR_Q_LOOKUP_IDS */
+typedef struct q_samr_lookup_ids_info
+{
+    POLICY_HND pol;       /* policy handle */
+
+       uint32 num_sids1;      /* number of rids being looked up */
+       uint32 ptr;            /* buffer pointer */
+       uint32 num_sids2;      /* number of rids being looked up */
+
+       uint32   ptr_sid[MAX_LOOKUP_SIDS]; /* pointers to sids to be looked up */
+       DOM_SID2 sid    [MAX_LOOKUP_SIDS]; /* sids to be looked up. */
+
+} SAMR_Q_LOOKUP_IDS;
+
+
+/* SAMR_R_LOOKUP_IDS */
+typedef struct r_samr_lookup_ids_info
+{
+       uint32 num_entries;
+       uint32 ptr; /* undocumented buffer pointer */
+
+       uint32 num_entries2; 
+       uint32 rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */
+
+       uint32 status; /* return code */
+
+} SAMR_R_LOOKUP_IDS;
+
+
+/****************************************************************************
+SAMR_Q_LOOKUP_NAMES - do a conversion from SID to RID.
+
+the policy handle allocated by an "samr open secret" call is associated
+with a SID.  this policy handle is what is queried here, *not* the SID
+itself.  the response to the lookup rids is relative to this SID.
+*****************************************************************************/
+/* SAMR_Q_LOOKUP_NAMES */
+typedef struct q_samr_lookup_names_info
+{
+    POLICY_HND pol;       /* policy handle */
+
+       uint32 num_rids1;      /* number of rids being looked up */
+       uint32 rid;            /* 0x0000 03e8 - RID of the server doing the query? */
+       uint32 ptr;            /* 0x0000 0000 - 32 bit unknown */
+       uint32 num_rids2;      /* number of rids being looked up */
+
+       UNIHDR  hdr_user_name[MAX_LOOKUP_SIDS]; /* unicode account name header */
+       UNISTR2 uni_user_name[MAX_LOOKUP_SIDS]; /* unicode account name string */
+
+} SAMR_Q_LOOKUP_NAMES;
+
+
+/* SAMR_R_LOOKUP_NAMES */
+typedef struct r_samr_lookup_names_info
+{
+       uint32 num_entries;
+       uint32 undoc_buffer; /* undocumented buffer pointer */
+
+       uint32 num_entries2; 
+       DOM_RID3 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */
+
+       uint32 num_entries3; 
+
+       uint32 status; /* return code */
+
+} SAMR_R_LOOKUP_NAMES;
+
+
+/****************************************************************************
+SAMR_Q_UNKNOWN_12 - do a conversion from RID groups to something.
+
+called to resolve domain RID groups.
+*****************************************************************************/
+/* SAMR_Q_UNKNOWN_12 */
+typedef struct q_samr_unknown_12_info
+{
+    POLICY_HND pol;       /* policy handle */
+
+       uint32 num_gids1;      /* number of rids being looked up */
+       uint32 rid;            /* 0x0000 03e8 - RID of the server doing the query? */
+       uint32 ptr;            /* 0x0000 0000 - 32 bit unknown */
+       uint32 num_gids2;      /* number of rids being looked up */
+
+       uint32 gid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */
+
+} SAMR_Q_UNKNOWN_12;
+
+
+/****************************************************************************
+SAMR_R_UNKNOWN_12 - do a conversion from group RID to names
+
+*****************************************************************************/
+/* SAMR_R_UNKNOWN_12 */
+typedef struct r_samr_unknown_12_info
+{
+    POLICY_HND pol;       /* policy handle */
+
+       uint32 num_aliases1;      /* number of aliases being looked up */
+       uint32 ptr_aliases;       /* pointer to aliases */
+       uint32 num_aliases2;      /* number of aliases being looked up */
+
+       UNIHDR  hdr_als_name[MAX_LOOKUP_SIDS]; /* unicode account name header */
+       UNISTR2 uni_als_name[MAX_LOOKUP_SIDS]; /* unicode account name string */
+
+       uint32 num_als_usrs1;      /* number of users in aliases being looked up */
+       uint32 ptr_als_usrs;       /* pointer to users in aliases */
+       uint32 num_als_usrs2;      /* number of users in aliases being looked up */
+
+       uint32 num_als_usrs[MAX_LOOKUP_SIDS]; /* number of users per group */
+
+       uint32 status;
+
+} SAMR_R_UNKNOWN_12;
+
+
+/* SAMR_Q_OPEN_USER - probably an open */
+typedef struct q_samr_open_user_info
+{
+    POLICY_HND domain_pol;       /* policy handle */
+       uint32 unknown_0;     /* 32 bit unknown - 0x02011b */
+       uint32 user_rid;      /* user RID */
+
+} SAMR_Q_OPEN_USER;
+
+
+/* SAMR_R_OPEN_USER - probably an open */
+typedef struct r_samr_open_user_info
+{
+    POLICY_HND user_pol;       /* policy handle associated with unknown id */
+       uint32 status;         /* return status */
+
+} SAMR_R_OPEN_USER;
+
+
+/* SAMR_Q_UNKNOWN_13 - probably an open alias in domain */
+typedef struct q_samr_unknown_13_info
+{
+    POLICY_HND alias_pol;        /* policy handle */
+
+       uint16 unknown_1;            /* 16 bit unknown - 0x0200 */
+       uint16 unknown_2;            /* 16 bit unknown - 0x0000 */
+
+} SAMR_Q_UNKNOWN_13;
+
+
+/* SAMR_Q_UNKNOWN_21 - probably an open group in domain */
+typedef struct q_samr_unknown_21_info
+{
+    POLICY_HND group_pol;        /* policy handle */
+
+       uint16 unknown_1;            /* 16 bit unknown - 0x0477 */
+       uint16 unknown_2;            /* 16 bit unknown - 0x0000 */
+
+} SAMR_Q_UNKNOWN_21;
+
+
+/* SAMR_Q_UNKNOWN_32 - probably a "create SAM entry" */
+typedef struct q_samr_unknown_32_info
+{
+    POLICY_HND pol;             /* policy handle */
+
+       UNIHDR  hdr_mach_acct;       /* unicode machine account name header */
+       UNISTR2 uni_mach_acct;       /* unicode machine account name */
+
+       uint32 acct_ctrl;            /* 32 bit ACB_XXXX */
+       uint16 unknown_1;            /* 16 bit unknown - 0x00B0 */
+       uint16 unknown_2;            /* 16 bit unknown - 0xe005 */
+
+} SAMR_Q_UNKNOWN_32;
+
+
+/* SAMR_R_UNKNOWN_32 - probably a "create SAM entry" */
+typedef struct r_samr_unknown_32_info
+{
+    POLICY_HND pol;       /* policy handle */
+
+       /* rid4.unknown - fail: 0030 success: 0x03ff */
+       DOM_RID4 rid4;         /* rid and attributes */
+
+       uint32 status;         /* return status - fail: 0xC000 0099: user exists */
+
+} SAMR_R_UNKNOWN_32;
+
+
+/* SAMR_Q_OPEN_ALIAS - probably an open */
+typedef struct q_samr_open_alias_info
+{
+       uint32 unknown_0;         /* 0x0000 0008 */
+       uint32 rid_alias;        /* rid */
+
+} SAMR_Q_OPEN_ALIAS;
+
+
+/* SAMR_R_OPEN_ALIAS - probably an open */
+typedef struct r_samr_open_alias_info
+{
+       POLICY_HND pol;       /* policy handle */
+       uint32 status;         /* return status */
+
+} SAMR_R_OPEN_ALIAS;
+
+
+/* SAMR_Q_CONNECT_ANON - probably an open */
+typedef struct q_samr_connect_anon_info
+{
+       uint32 ptr;                  /* ptr? */
+       uint16 unknown_0;            /* 0x005c */
+       uint16 unknown_1;            /* 0x0001 */
+       uint32 unknown_2;            /* 0x0000 0020 */
+
+} SAMR_Q_CONNECT_ANON;
+
+/* SAMR_R_CONNECT_ANON - probably an open */
+typedef struct r_samr_connect_anon_info
+{
+       POLICY_HND connect_pol;       /* policy handle */
+       uint32 status;         /* return status */
+
+} SAMR_R_CONNECT_ANON;
+
+/* SAMR_Q_CONNECT - probably an open */
+typedef struct q_samr_connect_info
+{
+       uint32 ptr_srv_name;         /* pointer (to server name?) */
+       UNISTR2 uni_srv_name;        /* unicode server name starting with '\\' */
+
+       uint32 unknown_0;            /* 32 bit unknown */
+
+} SAMR_Q_CONNECT;
+
+
+/* SAMR_R_CONNECT - probably an open */
+typedef struct r_samr_connect_info
+{
+    POLICY_HND connect_pol;       /* policy handle */
+       uint32 status;         /* return status */
+
+} SAMR_R_CONNECT;
+
+/* SAMR_Q_UNKNOWN_38 */
+typedef struct q_samr_unknown_38
+{
+       uint32 ptr; 
+       UNIHDR  hdr_srv_name;
+       UNISTR2 uni_srv_name;
+
+} SAMR_Q_UNKNOWN_38;
+
+/* SAMR_R_UNKNOWN_38 */
+typedef struct r_samr_unknown_38
+{
+       uint16 unk_0;
+       uint16 unk_1;
+       uint16 unk_2;
+       uint16 unk_3;
+
+} SAMR_R_UNKNOWN_38;
+
+/* SAMR_ENC_PASSWD */
+typedef struct enc_passwd_info
+{
+       uint32 ptr;
+       uint8 pass[516];
+
+} SAMR_ENC_PASSWD;
+
+/* SAMR_ENC_HASH */
+typedef struct enc_hash_info
+{
+       uint32 ptr;
+       uint8 hash[16];
+
+} SAMR_ENC_HASH;
+
+/* SAMR_Q_CHGPASSWD_USER */
+typedef struct q_samr_chgpasswd_user_info
+{
+       uint32 ptr_0;
+
+       UNIHDR hdr_dest_host; /* server name unicode header */
+       UNISTR2 uni_dest_host; /* server name unicode string */
+
+       UNIHDR hdr_user_name;    /* username unicode string header */
+       UNISTR2 uni_user_name;    /* username unicode string */
+
+       SAMR_ENC_PASSWD nt_newpass;
+       SAMR_ENC_HASH nt_oldhash;
+
+       uint32 unknown; /* 0x0000 0001 */
+
+       SAMR_ENC_PASSWD lm_newpass;
+       SAMR_ENC_HASH lm_oldhash;
+
+} SAMR_Q_CHGPASSWD_USER;
+
+/* SAMR_R_CHGPASSWD_USER */
+typedef struct r_samr_chgpasswd_user_info
+{
+       uint32 status; /* 0 == OK, C000006A (NT_STATUS_WRONG_PASSWORD) */
+
+} SAMR_R_CHGPASSWD_USER;
+
+#endif /* _RPC_SAMR_H */
+
index eea2f0716696c985f766e9f57369e07ce7cb8fbb..99f4dcc821f84b1e1643763cecc7512e868e4d24 100644 (file)
@@ -2958,3 +2958,56 @@ int set_maxfiles(int requested_max)
        return requested_max;
 #endif
 }
+
+
+/*****************************************************************
+ splits out the last subkey of a key
+ *****************************************************************/  
+void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
+{
+       split_at_last_component(full_keyname, key_name, '\\', subkey_name);
+}
+
+/*****************************************************************
+ splits out the start of the key (HKLM or HKU) and the rest of the key
+ *****************************************************************/  
+BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
+{
+       pstring tmp;
+
+       if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
+       {
+               return False;
+       }
+
+       (*reg_type) = 0;
+
+       DEBUG(10, ("reg_split_key: hive %s\n", tmp));
+
+       if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
+       {
+               (*reg_type) = HKEY_LOCAL_MACHINE;
+       }
+       else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
+       {
+               (*reg_type) = HKEY_USERS;
+       }
+       else
+       {
+               DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
+               return False;
+       }
+       
+       if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
+       {
+               fstrcpy(key_name, tmp);
+       }
+       else
+       {
+               key_name[0] = 0;
+       }
+
+       DEBUG(10, ("reg_split_key: name %s\n", key_name));
+
+       return True;
+}
index bcbece1f4a631d00f952f1dcfff3a56b9428ba96..5e6e101883c35a59700dd651bf0d5c872cc50842 100644 (file)
@@ -74,6 +74,25 @@ static void lsa_reply_open_policy(prs_struct *rdata)
        lsa_io_r_open_pol("", &r_o, rdata, 0);
 }
 
+/***************************************************************************
+make_dom_query
+ ***************************************************************************/
+static void make_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid)
+{
+       int domlen = strlen(dom_name);
+
+       d_q->uni_dom_max_len = domlen * 2;
+       d_q->uni_dom_str_len = domlen * 2;
+
+       d_q->buffer_dom_name = 4; /* domain buffer pointer */
+       d_q->buffer_dom_sid  = 2; /* domain sid pointer */
+
+       /* this string is supposed to be character short */
+       make_unistr2(&(d_q->uni_domain_name), dom_name, domlen);
+
+       make_dom_sid2(&(d_q->dom_sid), dom_sid);
+}
+
 /***************************************************************************
 lsa_reply_query_info
  ***************************************************************************/
@@ -93,24 +112,6 @@ static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e,
        lsa_io_r_enum_trust_dom("", &r_e, rdata, 0);
 }
 
-/***************************************************************************
-make_dom_query
- ***************************************************************************/
-static void make_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid)
-{
-       int domlen = strlen(dom_name);
-
-       d_q->uni_dom_max_len = domlen * 2;
-       d_q->uni_dom_str_len = domlen * 2;
-
-       d_q->buffer_dom_name = 4; /* domain buffer pointer */
-       d_q->buffer_dom_sid  = 2; /* domain sid pointer */
-
-       /* this string is supposed to be character short */
-       make_unistr2(&(d_q->uni_domain_name), dom_name, domlen);
-
-       make_dom_sid2(&(d_q->dom_sid), dom_sid);
-}
 /***************************************************************************
 lsa_reply_query_info
  ***************************************************************************/
@@ -135,6 +136,173 @@ static void lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata,
 }
 
 
+/***************************************************************************
+make_dom_ref
+ ***************************************************************************/
+static void make_dom_ref(DOM_R_REF *ref, int num_domains,
+                               char **dom_names, DOM_SID **dom_sids)
+                         
+{
+       int i;
+
+       if (num_domains > MAX_REF_DOMAINS)
+       {
+               num_domains = MAX_REF_DOMAINS;
+       }
+
+       ref->undoc_buffer = 1;
+       ref->num_ref_doms_1 = num_domains;
+       ref->undoc_buffer2 = 1;
+       ref->max_entries = MAX_REF_DOMAINS;
+       ref->num_ref_doms_2 = num_domains;
+
+       for (i = 0; i < num_domains; i++)
+       {
+               int len = dom_names[i] != NULL ? strlen(dom_names[i]) : 0;
+
+               make_uni_hdr(&(ref->hdr_ref_dom[i].hdr_dom_name), len, len, len != 0 ? 1 : 0);
+               ref->hdr_ref_dom[i].ptr_dom_sid = dom_sids[i] != NULL ? 1 : 0;
+
+               make_unistr2 (&(ref->ref_dom[i].uni_dom_name), dom_names[i], len);
+               make_dom_sid2(&(ref->ref_dom[i].ref_dom     ), dom_sids [i]);
+       }
+
+}
+
+/***************************************************************************
+make_reply_lookup_rids
+ ***************************************************************************/
+static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
+                               int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
+                               int num_ref_doms,
+                               char **dom_names, DOM_SID **dom_sids)
+{
+       int i;
+
+       make_dom_ref(&(r_l->dom_ref), num_ref_doms, dom_names, dom_sids);
+
+       r_l->num_entries = num_entries;
+       r_l->undoc_buffer = 1;
+       r_l->num_entries2 = num_entries;
+
+       SMB_ASSERT_ARRAY(r_l->dom_rid, num_entries);
+
+       for (i = 0; i < num_entries; i++)
+       {
+               make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i], 0x01);
+       }
+
+       r_l->num_entries3 = num_entries;
+}
+
+/***************************************************************************
+make_lsa_trans_names
+ ***************************************************************************/
+static void make_lsa_trans_names(LSA_TRANS_NAME_ENUM *trn,
+                               int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
+                               uint32 *total)
+{
+       uint32 status = 0x0;
+       int i;
+       (*total) = 0;
+
+       SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
+
+       for (i = 0; i < num_entries; i++)
+       {
+               uint32 rid = 0xffffffff;
+               uint8 num_auths = sid[i].sid.num_auths;
+               fstring name;
+               uint32 type;
+               
+               SMB_ASSERT_ARRAY(sid[i].sid.sub_auths, num_auths);
+
+               /* find the rid to look up */
+               if (num_auths != 0)
+               {
+                       rid = sid[i].sid.sub_auths[num_auths-1];
+
+                       status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
+
+                       status = (status != 0x0) ? lookup_user_name (rid, name, &type) : status;
+                       status = (status != 0x0) ? lookup_group_name(rid, name, &type) : status;
+                       status = (status != 0x0) ? lookup_alias_name(rid, name, &type) : status;
+               }
+
+               if (status == 0x0)
+               {
+                       make_lsa_trans_name(&(trn->name    [(*total)]),
+                                           &(trn->uni_name[(*total)]),
+                                           type, name, (*total));
+                       (*total)++;
+               }
+       }
+
+       trn->num_entries = (*total);
+       trn->ptr_trans_names = 1;
+       trn->num_entries2 = (*total);
+}
+
+/***************************************************************************
+make_reply_lookup_sids
+ ***************************************************************************/
+static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
+                               DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
+                               uint32 mapped_count, uint32 status)
+{
+       r_l->dom_ref      = ref;
+       r_l->names        = names;
+       r_l->mapped_count = mapped_count;
+       r_l->status       = status;
+}
+
+/***************************************************************************
+lsa_reply_lookup_sids
+ ***************************************************************************/
+static void lsa_reply_lookup_sids(prs_struct *rdata,
+                               int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
+                               int num_ref_doms,
+                               char **dom_names, DOM_SID **dom_sids)
+{
+       LSA_R_LOOKUP_SIDS r_l;
+       DOM_R_REF ref;
+       LSA_TRANS_NAME_ENUM names;
+       uint32 mapped_count = 0;
+
+       ZERO_STRUCT(r_l);
+       ZERO_STRUCT(ref);
+       ZERO_STRUCT(names);
+
+       /* set up the LSA Lookup SIDs response */
+       make_dom_ref(&ref, num_ref_doms, dom_names, dom_sids);
+       make_lsa_trans_names(&names, num_entries, sid, &mapped_count);
+       make_reply_lookup_sids(&r_l, &ref, &names, mapped_count, 0x0);
+
+       /* store the response in the SMB stream */
+       lsa_io_r_lookup_sids("", &r_l, rdata, 0);
+}
+
+/***************************************************************************
+lsa_reply_lookup_rids
+ ***************************************************************************/
+static void lsa_reply_lookup_rids(prs_struct *rdata,
+                               int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
+                               int num_ref_doms,
+                               char **dom_names, DOM_SID **dom_sids)
+{
+       LSA_R_LOOKUP_RIDS r_l;
+
+       ZERO_STRUCT(r_l);
+
+       /* set up the LSA Lookup RIDs response */
+       make_reply_lookup_rids(&r_l, num_entries, dom_rids,
+                               num_ref_doms, dom_names, dom_sids);
+       r_l.status = 0x0;
+
+       /* store the response in the SMB stream */
+       lsa_io_r_lookup_rids("", &r_l, rdata, 0);
+}
+
 /***************************************************************************
 api_lsa_open_policy
  ***************************************************************************/
@@ -210,6 +378,130 @@ static void api_lsa_query_info( uint16 vuid, prs_struct *data,
        lsa_reply_query_info(&q_i, rdata, dom_name, &global_sam_sid);
 }
 
+/***************************************************************************
+api_lsa_lookup_sids
+ ***************************************************************************/
+static void api_lsa_lookup_sids( uint16 vuid, prs_struct *data,
+                                 prs_struct *rdata )
+{
+       LSA_Q_LOOKUP_SIDS q_l;
+       pstring dom_name;
+       DOM_SID sid_S_1_1;
+       DOM_SID sid_S_1_3;
+       DOM_SID sid_S_1_5;
+
+       DOM_SID *sid_array[4];
+       char    *dom_names[4];
+
+       ZERO_STRUCT(q_l);
+       ZERO_STRUCT(sid_S_1_1);
+       ZERO_STRUCT(sid_S_1_3);
+       ZERO_STRUCT(sid_S_1_5);
+
+       /* grab the info class and policy handle */
+       lsa_io_q_lookup_sids("", &q_l, data, 0);
+
+       pstrcpy(dom_name, lp_workgroup());
+
+       string_to_sid(&sid_S_1_1, "S-1-1");
+        string_to_sid(&sid_S_1_3, "S-1-3");
+        string_to_sid(&sid_S_1_5, "S-1-5");
+
+       dom_names[0] = dom_name;
+       sid_array[0] = &global_sam_sid;
+
+       dom_names[1] = "Everyone";
+       sid_array[1] = &sid_S_1_1;
+
+       dom_names[2] = "don't know";
+       sid_array[2] = &sid_S_1_3;
+
+       dom_names[3] = "NT AUTHORITY";
+       sid_array[3] = &sid_S_1_5;
+
+       /* construct reply.  return status is always 0x0 */
+       lsa_reply_lookup_sids(rdata,
+                              q_l.sids.num_entries, q_l.sids.sid, /* SIDs */
+                              4, dom_names, sid_array);
+}
+
+/***************************************************************************
+api_lsa_lookup_names
+ ***************************************************************************/
+static void api_lsa_lookup_names( uint16 vuid, prs_struct *data,
+                                  prs_struct *rdata )
+{
+       int i;
+       LSA_Q_LOOKUP_RIDS q_l;
+       pstring dom_name;
+       uint32 dom_rids[MAX_LOOKUP_SIDS];
+       uint32 dummy_g_rid;
+
+       DOM_SID sid_S_1_1;
+       DOM_SID sid_S_1_3;
+       DOM_SID sid_S_1_5;
+
+       DOM_SID *sid_array[4];
+       char    *dom_names[4];
+
+       ZERO_STRUCT(q_l);
+       ZERO_STRUCT(sid_S_1_1);
+       ZERO_STRUCT(sid_S_1_3);
+       ZERO_STRUCT(sid_S_1_5);
+       ZERO_ARRAY(dom_rids);   
+
+       /* grab the info class and policy handle */
+       lsa_io_q_lookup_rids("", &q_l, data, 0);
+
+       pstrcpy(dom_name, lp_workgroup());
+
+       string_to_sid(&sid_S_1_1, "S-1-1");
+        string_to_sid(&sid_S_1_3, "S-1-3");
+        string_to_sid(&sid_S_1_5, "S-1-5");
+
+       dom_names[0] = dom_name;
+       sid_array[0] = &global_sam_sid;
+
+       dom_names[1] = "Everyone";
+       sid_array[1] = &sid_S_1_1;
+
+       dom_names[2] = "don't know";
+       sid_array[2] = &sid_S_1_3;
+
+       dom_names[3] = "NT AUTHORITY";
+       sid_array[3] = &sid_S_1_5;
+
+       SMB_ASSERT_ARRAY(q_l.lookup_name, q_l.num_entries);
+
+       /* convert received RIDs to strings, so we can do them. */
+       for (i = 0; i < q_l.num_entries; i++)
+       {
+               fstring user_name;
+               fstrcpy(user_name, unistr2(q_l.lookup_name[i].str.buffer));
+
+               /*
+                * Map to the UNIX username.
+                */
+               map_username(user_name);
+
+               /*
+                * Do any case conversions.
+                */
+               (void)Get_Pwnam(user_name, True);
+
+               if (!pdb_name_to_rid(user_name, &dom_rids[i], &dummy_g_rid))
+               {
+                       /* WHOOPS!  we should really do something about this... */
+                       dom_rids[i] = 0;
+               }
+       }
+
+       /* construct reply.  return status is always 0x0 */
+       lsa_reply_lookup_rids(rdata,
+                              q_l.num_entries, dom_rids, /* text-converted SIDs */
+                              4, dom_names, sid_array);
+}
+
 /***************************************************************************
  api_lsa_close
  ***************************************************************************/
@@ -271,6 +563,8 @@ static struct api_struct api_lsa_cmds[] =
        { "LSA_ENUMTRUSTDOM"    , LSA_ENUMTRUSTDOM    , api_lsa_enum_trust_dom },
        { "LSA_CLOSE"           , LSA_CLOSE           , api_lsa_close          },
        { "LSA_OPENSECRET"      , LSA_OPENSECRET      , api_lsa_open_secret    },
+       { "LSA_LOOKUPSIDS"      , LSA_LOOKUPSIDS      , api_lsa_lookup_sids    },
+       { "LSA_LOOKUPNAMES"     , LSA_LOOKUPNAMES     , api_lsa_lookup_names   },
        { NULL                  , 0                   , NULL                   }
 };
 
index de2fe66c3e82dd03632fcf89ec69c4123457f3bf..dc92bcd4e8cfb128877ad7fa8d8627a1487d5d8a 100644 (file)
@@ -2234,7 +2234,7 @@ Display the contents of the global structure.
 static void dump_globals(FILE *f)
 {
        int i;
-       fprintf(f, "[global]\n");
+       fprintf(f, "# Global parameters\n");
        
        for (i=0;parm_table[i].label;i++)
                if (parm_table[i].class == P_GLOBAL &&
index 320c2c794df93f32c310fcccb171a2c6d31761ec..5255732c5dd03712ce99c2ab89b979a67c322825 100644 (file)
@@ -98,6 +98,115 @@ BOOL do_lsa_open_policy(struct cli_state *cli,
        return valid_pol;
 }
 
+/****************************************************************************
+do a LSA Lookup SIDs
+****************************************************************************/
+BOOL do_lsa_lookup_sids(struct cli_state *cli,
+                       POLICY_HND *hnd,
+                       int num_sids,
+                       DOM_SID **sids,
+                       char ***names,
+                       int *num_names)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       LSA_Q_LOOKUP_SIDS q_l;
+       BOOL valid_response = False;
+
+       if (hnd == NULL || num_sids == 0 || sids == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api LSA_LOOKUP_SIDS */
+
+       DEBUG(4,("LSA Lookup SIDs\n"));
+
+       /* store the parameters */
+       make_q_lookup_sids(&q_l, hnd, num_sids, sids, 1);
+
+       /* turn parameters into data stream */
+       lsa_io_q_lookup_sids("", &q_l, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, LSA_LOOKUPSIDS, &buf, &rbuf))
+       {
+               LSA_R_LOOKUP_SIDS r_l;
+               DOM_R_REF ref;
+               LSA_TRANS_NAME_ENUM t_names;
+               BOOL p;
+
+               r_l.dom_ref = &ref;
+               r_l.names   = &t_names;
+
+               lsa_io_r_lookup_sids("", &r_l, &rbuf, 0);
+               p = rbuf.offset != 0;
+               
+               if (p && r_l.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("LSA_LOOKUP_SIDS: %s\n", get_nt_error_msg(r_l.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       if (t_names.ptr_trans_names != 0 && ref.undoc_buffer != 0)
+                       {
+                               valid_response = True;
+                       }
+               }
+
+               if (num_names != NULL && valid_response)
+               {
+                       (*num_names) = t_names.num_entries;
+               }
+               if (valid_response)
+               {
+                       int i;
+                       for (i = 0; i < t_names.num_entries; i++)
+                       {
+                               if (t_names.name[i].domain_idx >= ref.num_ref_doms_1)
+                               {
+                                       DEBUG(0,("LSA_LOOKUP_SIDS: domain index out of bounds\n"));
+                                       valid_response = False;
+                                       break;
+                               }
+                       }
+               }
+
+               if (names != NULL && valid_response && t_names.num_entries != 0)
+               {
+                       (*names) = (char**)malloc((*num_names) * sizeof(char*));
+               }
+
+               if (names != NULL && (*names) != NULL)
+               {
+                       int i;
+                       /* take each name, construct a \DOMAIN\name string */
+                       for (i = 0; i < (*num_names); i++)
+                       {
+                               fstring name;
+                               fstring dom_name;
+                               fstring full_name;
+                               uint32 dom_idx = t_names.name[i].domain_idx;
+                               fstrcpy(dom_name, unistr2(ref.ref_dom[dom_idx].uni_dom_name.buffer));
+                               fstrcpy(name    , unistr2(t_names.uni_name[i].buffer));
+                               
+                               slprintf(full_name, sizeof(full_name)-1, "\\%s\\%s",
+                                        dom_name, name);
+
+                               (*names)[i] = strdup(full_name);
+                       }
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_response;
+}
+
 /****************************************************************************
 do a LSA Query Info Policy
 ****************************************************************************/
index fe8bf4e7ff8af7e1c8e6c90125cdd20e3e9f87a3..a2ab8b1e0cfbba6958437d0514a664893c903fe2 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* removed in SAMBA_2_0 branch. */
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/****************************************************************************
+do a REG Open Policy
+****************************************************************************/
+BOOL do_reg_connect(struct cli_state *cli, char *full_keyname, char *key_name,
+                               POLICY_HND *reg_hnd)
+{
+       BOOL res = True;
+       uint32 reg_type = 0;
+
+       if (full_keyname == NULL)
+       {
+               return False;
+       }
+
+       ZERO_STRUCTP(reg_hnd);
+
+       /*
+        * open registry receive a policy handle
+        */
+
+       if (!reg_split_key(full_keyname, &reg_type, key_name))
+       {
+               DEBUG(0,("do_reg_connect: unrecognised key name %s\n", full_keyname));  
+               return False;
+       }
+
+       switch (reg_type)
+       {
+               case HKEY_LOCAL_MACHINE:
+               {
+                       res = res ? do_reg_open_hklm(cli,
+                                       0x84E0, 0x02000000,
+                                       reg_hnd) : False;
+                       break;
+               }
+       
+               case HKEY_USERS:
+               {
+                       res = res ? do_reg_open_hku(cli,
+                                       0x84E0, 0x02000000,
+                                       reg_hnd) : False;
+                       break;
+               }
+               default:
+               {
+                       DEBUG(0,("do_reg_connect: unrecognised hive key\n"));   
+                       return False;
+               }
+       }
+
+       return res;
+}
+
+/****************************************************************************
+do a REG Open Policy
+****************************************************************************/
+BOOL do_reg_open_hklm(struct cli_state *cli, uint16 unknown_0, uint32 level,
+                               POLICY_HND *hnd)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_OPEN_HKLM q_o;
+       BOOL valid_pol = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_OPEN_HKLM */
+
+       DEBUG(4,("REG Open HKLM\n"));
+
+       make_reg_q_open_hklm(&q_o, unknown_0, level);
+
+       /* turn parameters into data stream */
+       reg_io_q_open_hklm("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_OPEN_HKLM, &buf, &rbuf))
+       {
+               REG_R_OPEN_HKLM r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_open_hklm("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_OPEN_HKLM: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       /* ok, at last: we're happy. return the policy handle */
+                       memcpy(hnd, r_o.pol.data, sizeof(hnd->data));
+                       valid_pol = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_pol;
+}
+
+/****************************************************************************
+do a REG Open HKU
+****************************************************************************/
+BOOL do_reg_open_hku(struct cli_state *cli, uint16 unknown_0, uint32 level,
+                               POLICY_HND *hnd)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_OPEN_HKU q_o;
+       BOOL valid_pol = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_OPEN_HKU */
+
+       DEBUG(4,("REG Open HKU\n"));
+
+       make_reg_q_open_hku(&q_o, unknown_0, level);
+
+       /* turn parameters into data stream */
+       reg_io_q_open_hku("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_OPEN_HKU, &buf, &rbuf))
+       {
+               REG_R_OPEN_HKU r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_open_hku("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_OPEN_HKU: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       /* ok, at last: we're happy. return the policy handle */
+                       memcpy(hnd, r_o.pol.data, sizeof(hnd->data));
+                       valid_pol = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_pol;
+}
+
+/****************************************************************************
+do a REG Unknown 0xB command.  sent after a create key or create value.
+this might be some sort of "sync" or "refresh" command, sent after
+modification of the registry...
+****************************************************************************/
+BOOL do_reg_flush_key(struct cli_state *cli, POLICY_HND *hnd)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_FLUSH_KEY q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_FLUSH_KEY */
+
+       DEBUG(4,("REG Unknown 0xB\n"));
+
+       make_reg_q_flush_key(&q_o, hnd);
+
+       /* turn parameters into data stream */
+       reg_io_q_flush_key("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_FLUSH_KEY, &buf, &rbuf))
+       {
+               REG_R_FLUSH_KEY r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_flush_key("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_FLUSH_KEY: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_query = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Query Key
+****************************************************************************/
+BOOL do_reg_query_key(struct cli_state *cli, POLICY_HND *hnd,
+                               char *class, uint32 *class_len,
+                               uint32 *num_subkeys, uint32 *max_subkeylen,
+                               uint32 *max_subkeysize, uint32 *num_values,
+                               uint32 *max_valnamelen, uint32 *max_valbufsize,
+                               uint32 *sec_desc, NTTIME *mod_time)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_QUERY_KEY q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_QUERY_KEY */
+
+       DEBUG(4,("REG Query Key\n"));
+
+       make_reg_q_query_key(&q_o, hnd, *class_len);
+
+       /* turn parameters into data stream */
+       reg_io_q_query_key("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_QUERY_KEY, &buf, &rbuf))
+       {
+               REG_R_QUERY_KEY r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_query_key("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_QUERY_KEY: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_query = True;
+                       
+                       *class_len      = r_o.hdr_class.uni_max_len;
+                       fstrcpy(class, unistr2_to_str(&r_o.uni_class));
+                       *num_subkeys    = r_o.num_subkeys   ;
+                       *max_subkeylen  = r_o.max_subkeylen ;
+                       *max_subkeysize = r_o.max_subkeysize;
+                       *num_values     = r_o.num_values    ;
+                       *max_valnamelen = r_o.max_valnamelen;
+                       *max_valbufsize = r_o.max_valbufsize;
+                       *sec_desc       = r_o.sec_desc      ;
+                       *mod_time       = r_o.mod_time      ;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Unknown 1A
+****************************************************************************/
+BOOL do_reg_unknown_1a(struct cli_state *cli, POLICY_HND *hnd, uint32 *unk)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_UNK_1A q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_UNKNOWN_1A */
+
+       DEBUG(4,("REG Unknown 1a\n"));
+
+       make_reg_q_unk_1a(&q_o, hnd);
+
+       /* turn parameters into data stream */
+       reg_io_q_unk_1a("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_UNK_1A, &buf, &rbuf))
+       {
+               REG_R_UNK_1A r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_unk_1a("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_UNK_1A: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_query = True;
+                       (*unk) = r_o.unknown;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Query Info
+****************************************************************************/
+BOOL do_reg_query_info(struct cli_state *cli, POLICY_HND *hnd,
+                               char *type, uint32 *unk_0, uint32 *unk_1)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_INFO q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_INFO */
+
+       DEBUG(4,("REG Query Info\n"));
+
+       make_reg_q_info(&q_o, hnd, "ProductType", time(NULL), 4, 1);
+
+       /* turn parameters into data stream */
+       reg_io_q_info("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_INFO, &buf, &rbuf))
+       {
+               REG_R_INFO r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_info("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_INFO: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_query = True;
+                       fstrcpy(type, buffer2_to_str(&r_o.uni_type));
+                       (*unk_0) = r_o.unknown_0;
+                       (*unk_1) = r_o.unknown_1;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Set Key Security 
+****************************************************************************/
+BOOL do_reg_set_key_sec(struct cli_state *cli, POLICY_HND *hnd, SEC_DESC_BUF *sec_desc_buf)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_SET_KEY_SEC q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_SET_KEY_SEC */
+
+       DEBUG(4,("REG Set Key security.\n"));
+
+       make_reg_q_set_key_sec(&q_o, hnd, sec_desc_buf);
+
+       /* turn parameters into data stream */
+       reg_io_q_set_key_sec("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_SET_KEY_SEC, &buf, &rbuf))
+       {
+               REG_R_SET_KEY_SEC r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_set_key_sec("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       valid_query = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Query Key Security 
+****************************************************************************/
+
+BOOL do_reg_get_key_sec(struct cli_state *cli, POLICY_HND *hnd, uint32 *sec_buf_size, SEC_DESC_BUF **ppsec_desc_buf)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_GET_KEY_SEC q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_GET_KEY_SEC */
+
+       DEBUG(4,("REG query key security.  buf_size: %d\n", *sec_buf_size));
+
+       make_reg_q_get_key_sec(&q_o, hnd, *sec_buf_size, NULL);
+
+       /* turn parameters into data stream */
+       reg_io_q_get_key_sec("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_GET_KEY_SEC, &buf, &rbuf))
+       {
+               REG_R_GET_KEY_SEC r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_get_key_sec("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status == 0x0000007a)
+               {
+                       /*
+                        * get the maximum buffer size: it was too small
+                        */
+                       (*sec_buf_size) = r_o.hdr_sec.buf_max_len;
+                       DEBUG(5,("sec_buf_size too small.  use %d\n", *sec_buf_size));
+                       valid_query = True;
+               }
+               else if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_GET_KEY_SEC: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+               else
+               {
+                       valid_query = True;
+                       (*sec_buf_size) = r_o.data->len;
+                       *ppsec_desc_buf = r_o.data;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Delete Value
+****************************************************************************/
+BOOL do_reg_delete_val(struct cli_state *cli, POLICY_HND *hnd, char *val_name)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_DELETE_VALUE q_o;
+       BOOL valid_delete = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_DELETE_VALUE */
+
+       DEBUG(4,("REG Delete Value: %s\n", val_name));
+
+       make_reg_q_delete_val(&q_o, hnd, val_name);
+
+       /* turn parameters into data stream */
+       reg_io_q_delete_val("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_DELETE_VALUE, &buf, &rbuf))
+       {
+               REG_R_DELETE_VALUE r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_delete_val("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_DELETE_VALUE: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_delete = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_delete;
+}
+
+/****************************************************************************
+do a REG Delete Key
+****************************************************************************/
+BOOL do_reg_delete_key(struct cli_state *cli, POLICY_HND *hnd, char *key_name)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_DELETE_KEY q_o;
+       BOOL valid_delete = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_DELETE_KEY */
+
+       DEBUG(4,("REG Delete Key: %s\n", key_name));
+
+       make_reg_q_delete_key(&q_o, hnd, key_name);
+
+       /* turn parameters into data stream */
+       reg_io_q_delete_key("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_DELETE_KEY, &buf, &rbuf))
+       {
+               REG_R_DELETE_KEY r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_delete_key("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_DELETE_KEY: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_delete = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_delete;
+}
+
+/****************************************************************************
+do a REG Create Key
+****************************************************************************/
+BOOL do_reg_create_key(struct cli_state *cli, POLICY_HND *hnd,
+                               char *key_name, char *key_class,
+                               SEC_ACCESS *sam_access,
+                               POLICY_HND *key)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_CREATE_KEY q_o;
+       BOOL valid_create = False;
+       SEC_DESC *sec;
+       SEC_DESC_BUF *sec_buf;
+       size_t sec_len;
+
+       ZERO_STRUCT(sec);
+       ZERO_STRUCT(sec_buf);
+       ZERO_STRUCT(q_o);
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_CREATE_KEY */
+
+       DEBUG(4,("REG Create Key: %s %s 0x%08x\n", key_name, key_class,
+               sam_access != NULL ? sam_access->mask : 0));
+
+       if((sec = make_sec_desc( 1, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, NULL, &sec_len)) == NULL)
+       {
+               DEBUG(0,("make_sec_desc : malloc fail.\n"));
+               return False;
+       }
+
+       DEBUG(10,("make_sec_desc: len = %d\n", sec_len));
+
+       if((sec_buf = make_sec_desc_buf( (int)sec_len, sec)) == NULL)
+       {
+               DEBUG(0,("make_sec_desc : malloc fail (1)\n"));
+               free_sec_desc(&sec);
+               return False;
+       }
+       free_sec_desc(&sec);
+
+       make_reg_q_create_key(&q_o, hnd, key_name, key_class, sam_access, sec_buf);
+
+       /* turn parameters into data stream */
+       reg_io_q_create_key("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_CREATE_KEY, &buf, &rbuf))
+       {
+               REG_R_CREATE_KEY r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_create_key("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_CREATE_KEY: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_create = True;
+                       memcpy(key, r_o.key_pol.data, sizeof(key->data));
+               }
+       }
+
+       free_sec_desc_buf(&sec_buf);
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_create;
+}
+
+/****************************************************************************
+do a REG Enum Key
+****************************************************************************/
+BOOL do_reg_enum_key(struct cli_state *cli, POLICY_HND *hnd,
+                               int key_index, char *key_name,
+                               uint32 *unk_1, uint32 *unk_2,
+                               time_t *mod_time)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_ENUM_KEY q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_ENUM_KEY */
+
+       DEBUG(4,("REG Enum Key\n"));
+
+       make_reg_q_enum_key(&q_o, hnd, key_index);
+
+       /* turn parameters into data stream */
+       reg_io_q_enum_key("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_ENUM_KEY, &buf, &rbuf))
+       {
+               REG_R_ENUM_KEY r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_enum_key("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_ENUM_KEY: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_query = True;
+                       (*unk_1) = r_o.unknown_1;
+                       (*unk_2) = r_o.unknown_2;
+                       fstrcpy(key_name, unistr2(r_o.key_name.str.buffer));
+                       (*mod_time) = nt_time_to_unix(&r_o.time);
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Create Value
+****************************************************************************/
+BOOL do_reg_create_val(struct cli_state *cli, POLICY_HND *hnd,
+                               char *val_name, uint32 type, BUFFER3 *data)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_CREATE_VALUE q_o;
+       BOOL valid_create = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_CREATE_VALUE */
+
+       DEBUG(4,("REG Create Value: %s\n", val_name));
+
+       make_reg_q_create_val(&q_o, hnd, val_name, type, data);
+
+       /* turn parameters into data stream */
+       reg_io_q_create_val("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_CREATE_VALUE, &buf, &rbuf))
+       {
+               REG_R_CREATE_VALUE r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_create_val("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_CREATE_VALUE: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_create = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_create;
+}
+
+/****************************************************************************
+do a REG Enum Value
+****************************************************************************/
+BOOL do_reg_enum_val(struct cli_state *cli, POLICY_HND *hnd,
+                               int val_index, int max_valnamelen, int max_valbufsize,
+                               fstring val_name,
+                               uint32 *val_type, BUFFER2 *value)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_ENUM_VALUE q_o;
+       BOOL valid_query = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_ENUM_VALUE */
+
+       DEBUG(4,("REG Enum Value\n"));
+
+       make_reg_q_enum_val(&q_o, hnd, val_index, max_valnamelen, max_valbufsize);
+
+       /* turn parameters into data stream */
+       reg_io_q_enum_val("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_ENUM_VALUE, &buf, &rbuf))
+       {
+               REG_R_ENUM_VALUE r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+               r_o.buf_value = value;
+
+               reg_io_r_enum_val("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_ENUM_VALUE: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_query = True;
+                       (*val_type) = r_o.type;
+                       fstrcpy(val_name, unistr2_to_str(&r_o.uni_name));
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a REG Open Key
+****************************************************************************/
+BOOL do_reg_open_entry(struct cli_state *cli, POLICY_HND *hnd,
+                               char *key_name, uint32 unk_0,
+                               POLICY_HND *key_hnd)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_OPEN_ENTRY q_o;
+       BOOL valid_pol = False;
+
+       if (hnd == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api REG_OPEN_ENTRY */
+
+       DEBUG(4,("REG Open Entry\n"));
+
+       make_reg_q_open_entry(&q_o, hnd, key_name, unk_0);
+
+       /* turn parameters into data stream */
+       reg_io_q_open_entry("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_OPEN_ENTRY, &buf, &rbuf))
+       {
+               REG_R_OPEN_ENTRY r_o;
+               BOOL p;
+
+               ZERO_STRUCT(r_o);
+
+               reg_io_r_open_entry("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_OPEN_ENTRY: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_pol = True;
+                       memcpy(key_hnd, r_o.pol.data, sizeof(key_hnd->data));
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_pol;
+}
+
+/****************************************************************************
+do a REG Close
+****************************************************************************/
+BOOL do_reg_close(struct cli_state *cli, POLICY_HND *hnd)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       REG_Q_CLOSE q_c;
+       BOOL valid_close = False;
+
+       if (hnd == NULL) return False;
+
+       /* create and send a MSRPC command with api REG_CLOSE */
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("REG Close\n"));
+
+       /* store the parameters */
+       make_reg_q_close(&q_c, hnd);
+
+       /* turn parameters into data stream */
+       reg_io_q_close("", &q_c, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, REG_CLOSE, &buf, &rbuf))
+       {
+               REG_R_CLOSE r_c;
+               BOOL p;
+
+               ZERO_STRUCT(r_c);
+
+               reg_io_r_close("", &r_c, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_c.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("REG_CLOSE: %s\n", get_nt_error_msg(r_c.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       /* check that the returned policy handle is all zeros */
+                       int i;
+                       valid_close = True;
+
+                       for (i = 0; i < sizeof(r_c.pol.data); i++)
+                       {
+                               if (r_c.pol.data[i] != 0)
+                               {
+                                       valid_close = False;
+                                       break;
+                               }
+                       }       
+                       if (!valid_close)
+                       {
+                               DEBUG(0,("REG_CLOSE: non-zero handle returned\n"));
+                       }
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_close;
+}
+
+
index 24f59b4f640c1947b2d4df87a7fe52c0bef7e50f..2deed85a16fd8b16d1fe96804d44c4328abcc29d 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+
+
+/****************************************************************************
+do a SAMR query user groups
+****************************************************************************/
+BOOL get_samr_query_usergroups(struct cli_state *cli, 
+                               POLICY_HND *pol_open_domain, uint32 user_rid,
+                               uint32 *num_groups, DOM_GID *gid)
+{
+       POLICY_HND pol_open_user;
+       if (pol_open_domain == NULL || num_groups == NULL || gid == NULL) return False;
+
+       /* send open domain (on user sid) */
+       if (!do_samr_open_user(cli,
+                               pol_open_domain,
+                               0x02011b, user_rid,
+                               &pol_open_user))
+       {
+               return False;
+       }
+
+       /* send user groups query */
+       if (!do_samr_query_usergroups(cli,
+                               &pol_open_user,
+                               num_groups, gid))
+       {
+               DEBUG(5,("do_samr_query_usergroups: error in query user groups\n"));
+       }
+
+       return do_samr_close(cli, &pol_open_user);
+}
+
+/****************************************************************************
+do a SAMR query user info
+****************************************************************************/
+BOOL get_samr_query_userinfo(struct cli_state *cli, 
+                               POLICY_HND *pol_open_domain,
+                               uint32 info_level,
+                               uint32 user_rid, SAM_USER_INFO_21 *usr)
+{
+       POLICY_HND pol_open_user;
+       if (pol_open_domain == NULL || usr == NULL) return False;
+
+       memset((char *)usr, '\0', sizeof(*usr));
+
+       /* send open domain (on user sid) */
+       if (!do_samr_open_user(cli,
+                               pol_open_domain,
+                               0x02011b, user_rid,
+                               &pol_open_user))
+       {
+               return False;
+       }
+
+       /* send user info query */
+       if (!do_samr_query_userinfo(cli,
+                               &pol_open_user,
+                               info_level, (void*)usr))
+       {
+               DEBUG(5,("do_samr_query_userinfo: error in query user info, level 0x%x\n",
+                         info_level));
+       }
+
+       return do_samr_close(cli, &pol_open_user);
+}
+
+/****************************************************************************
+do a SAMR change user password command
+****************************************************************************/
+BOOL do_samr_chgpasswd_user(struct cli_state *cli,
+               char *srv_name, char *user_name,
+               char nt_newpass[516], uchar nt_oldhash[16],
+               char lm_newpass[516], uchar lm_oldhash[16])
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_CHGPASSWD_USER q_e;
+       BOOL valid_pwc = False;
+
+       /* create and send a MSRPC command with api SAMR_CHGPASSWD_USER */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Change User Password. server:%s username:%s\n",
+               srv_name, user_name));
+
+       make_samr_q_chgpasswd_user(&q_e, srv_name, user_name,
+                                  nt_newpass, nt_oldhash,
+                                  lm_newpass, lm_oldhash);
+
+       /* turn parameters into data stream */
+       samr_io_q_chgpasswd_user("", &q_e, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_CHGPASSWD_USER, &data, &rdata))
+       {
+               SAMR_R_CHGPASSWD_USER r_e;
+               BOOL p;
+
+               samr_io_r_chgpasswd_user("", &r_e, &rdata, 0);
+
+               p = rdata.offset != 0;
+               if (p && r_e.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_CHGPASSWD_USER: %s\n", get_nt_error_msg(r_e.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_pwc = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_pwc;
+}
+
+/****************************************************************************
+do a SAMR unknown 0x38 command
+****************************************************************************/
+BOOL do_samr_unknown_38(struct cli_state *cli, char *srv_name)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_UNKNOWN_38 q_e;
+       BOOL valid_un8 = False;
+
+       /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Unknown 38 server:%s\n", srv_name));
+
+       make_samr_q_unknown_38(&q_e, srv_name);
+
+       /* turn parameters into data stream */
+       samr_io_q_unknown_38("", &q_e, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_UNKNOWN_38, &data, &rdata))
+       {
+               SAMR_R_UNKNOWN_38 r_e;
+               BOOL p;
+
+               samr_io_r_unknown_38("", &r_e, &rdata, 0);
+
+               p = rdata.offset != 0;
+#if 0
+               if (p && r_e.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_UNKNOWN_38: %s\n", get_nt_error_msg(r_e.status)));
+                       p = False;
+               }
+#endif
+               if (p)
+               {
+                       valid_un8 = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_un8;
+}
+
+/****************************************************************************
+do a SAMR unknown 0x8 command
+****************************************************************************/
+BOOL do_samr_query_dom_info(struct cli_state *cli, 
+                               POLICY_HND *domain_pol, uint16 switch_value)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_QUERY_DOMAIN_INFO q_e;
+       BOOL valid_un8 = False;
+
+       /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value));
+
+       if (domain_pol == NULL) return False;
+
+       /* store the parameters */
+       make_samr_q_query_dom_info(&q_e, domain_pol, switch_value);
+
+       /* turn parameters into data stream */
+       samr_io_q_query_dom_info("", &q_e, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &data, &rdata))
+       {
+#if 0
+               SAMR_R_QUERY_DOMAIN_INFO r_e;
+               BOOL p;
+
+               samr_io_r_query_dom_info("", &r_e, &rdata, 0);
+
+               p = rdata.offset != 0;
+               if (p && r_e.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_QUERY_DOMAIN_INFO: %s\n", get_nt_error_msg(r_e.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_un8 = True;
+               }
+#endif
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_un8;
+}
+
+/****************************************************************************
+do a SAMR enumerate users
+****************************************************************************/
+BOOL do_samr_enum_dom_users(struct cli_state *cli, 
+                               POLICY_HND *pol, uint16 num_entries, uint16 unk_0,
+                               uint16 acb_mask, uint16 unk_1, uint32 size,
+                               struct acct_info **sam,
+                               int *num_sam_users)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_ENUM_DOM_USERS q_e;
+    BOOL valid_pol = False;
+
+       /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size));
+
+       if (pol == NULL || num_sam_users == NULL) return False;
+
+       /* store the parameters */
+       make_samr_q_enum_dom_users(&q_e, pol,
+                                  num_entries, unk_0,
+                                  acb_mask, unk_1, size);
+
+       /* turn parameters into data stream */
+       samr_io_q_enum_dom_users("", &q_e, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_ENUM_DOM_USERS, &data, &rdata))
+       {
+               SAMR_R_ENUM_DOM_USERS r_e;
+               BOOL p;
+
+               samr_io_r_enum_dom_users("", &r_e, &rdata, 0);
+
+               p = rdata.offset != 0;
+               if (p && r_e.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", get_nt_error_msg(r_e.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       int i;
+                       int name_idx = 0;
+
+                       *num_sam_users = r_e.num_entries2;
+                       if (*num_sam_users > MAX_SAM_ENTRIES)
+                       {
+                               *num_sam_users = MAX_SAM_ENTRIES;
+                               DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n",
+                                         *num_sam_users));
+                       }
+
+                       *sam = (struct acct_info*) malloc(sizeof(struct acct_info) * (*num_sam_users));
+                                   
+                       if ((*sam) == NULL)
+                       {
+                               *num_sam_users = 0;
+                       }
+
+                       for (i = 0; i < *num_sam_users; i++)
+                       {
+
+                               (*sam)[i].smb_userid = r_e.sam[i].rid;
+                               if (r_e.sam[i].hdr_name.buffer)
+                               {
+                                       char *acct_name = unistrn2(r_e.uni_acct_name[name_idx].buffer,
+                                                                  r_e.uni_acct_name[name_idx].uni_str_len);
+                                       fstrcpy((*sam)[i].acct_name, acct_name);
+                                       name_idx++;
+                               }
+                               else
+                               {
+                                       memset((char *)(*sam)[i].acct_name, '\0', sizeof((*sam)[i].acct_name));
+                               }
+                               DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n",
+                                         i, (*sam)[i].smb_userid, (*sam)[i].acct_name));
+                       }
+                       valid_pol = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Connect
+****************************************************************************/
+BOOL do_samr_connect(struct cli_state *cli, 
+                               char *srv_name, uint32 unknown_0,
+                               POLICY_HND *connect_pol)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_CONNECT q_o;
+    BOOL valid_pol = False;
+
+       /* create and send a MSRPC command with api SAMR_CONNECT */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n",
+                               srv_name, unknown_0));
+
+       if (srv_name == NULL || connect_pol == NULL) return False;
+
+       /* store the parameters */
+       make_samr_q_connect(&q_o, srv_name, unknown_0);
+
+       /* turn parameters into data stream */
+       samr_io_q_connect("", &q_o,  &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_CONNECT, &data, &rdata))
+       {
+               SAMR_R_CONNECT r_o;
+               BOOL p;
+
+               samr_io_r_connect("", &r_o, &rdata, 0);
+               p = rdata.offset != 0;
+               
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_CONNECT: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol));
+                       valid_pol = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Open User
+****************************************************************************/
+BOOL do_samr_open_user(struct cli_state *cli, 
+                               POLICY_HND *pol, uint32 unk_0, uint32 rid, 
+                               POLICY_HND *user_pol)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_OPEN_USER q_o;
+    BOOL valid_pol = False;
+
+       /* create and send a MSRPC command with api SAMR_OPEN_USER */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Open User.  unk_0: %08x RID:%x\n",
+                 unk_0, rid));
+
+       if (pol == NULL || user_pol == NULL) return False;
+
+       /* store the parameters */
+       make_samr_q_open_user(&q_o, pol, unk_0, rid);
+
+       /* turn parameters into data stream */
+       samr_io_q_open_user("", &q_o,  &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_OPEN_USER, &data, &rdata))
+       {
+               SAMR_R_OPEN_USER r_o;
+               BOOL p;
+
+               samr_io_r_open_user("", &r_o, &rdata, 0);
+               p = rdata.offset != 0;
+               
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_OPEN_USER: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol));
+                       valid_pol = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Open Domain
+****************************************************************************/
+BOOL do_samr_open_domain(struct cli_state *cli, 
+                               POLICY_HND *connect_pol, uint32 rid, DOM_SID *sid,
+                               POLICY_HND *domain_pol)
+{
+       pstring sid_str;
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_OPEN_DOMAIN q_o;
+       BOOL valid_pol = False;
+
+       /* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       sid_to_string(sid_str, sid);
+       DEBUG(4,("SAMR Open Domain.  SID:%s RID:%x\n", sid_str, rid));
+
+       if (connect_pol == NULL || sid == NULL || domain_pol == NULL) return False;
+
+       /* store the parameters */
+       make_samr_q_open_domain(&q_o, connect_pol, rid, sid);
+
+       /* turn parameters into data stream */
+       samr_io_q_open_domain("", &q_o,  &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &data, &rdata))
+       {
+               SAMR_R_OPEN_DOMAIN r_o;
+               BOOL p;
+
+               samr_io_r_open_domain("", &r_o, &rdata, 0);
+               p = rdata.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol));
+                       valid_pol = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Query Unknown 12
+****************************************************************************/
+BOOL do_samr_query_unknown_12(struct cli_state *cli, 
+                               POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids,
+                               uint32 *num_aliases,
+                               fstring als_names    [MAX_LOOKUP_SIDS],
+                               uint32  num_als_users[MAX_LOOKUP_SIDS])
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_UNKNOWN_12 q_o;
+    BOOL valid_query = False;
+
+       /* create and send a MSRPC command with api SAMR_UNKNOWN_12 */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Query Unknown 12.\n"));
+
+       if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL ||
+           num_aliases == NULL || als_names == NULL || num_als_users == NULL ) return False;
+
+       /* store the parameters */
+       make_samr_q_unknown_12(&q_o, pol, rid, num_gids, gids);
+
+       /* turn parameters into data stream */
+       samr_io_q_unknown_12("", &q_o,  &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_UNKNOWN_12, &data, &rdata))
+       {
+               SAMR_R_UNKNOWN_12 r_o;
+               BOOL p;
+
+               samr_io_r_unknown_12("", &r_o, &rdata, 0);
+               p = rdata.offset != 0;
+               
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 &&
+                           r_o.num_als_usrs1 == r_o.num_aliases1)
+                       {
+                               int i;
+
+                               valid_query = True;
+                               *num_aliases = r_o.num_aliases1;
+
+                               for (i = 0; i < r_o.num_aliases1; i++)
+                               {
+                                       fstrcpy(als_names[i], unistrn2(r_o.uni_als_name[i].buffer, r_o.uni_als_name[i].uni_str_len));
+                               }
+                               for (i = 0; i < r_o.num_als_usrs1; i++)
+                               {
+                                       num_als_users[i] = r_o.num_als_usrs[i];
+                               }
+                       }
+                       else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0)
+                       {
+                               valid_query = True;
+                               *num_aliases = 0;
+                       }
+                       else
+                       {
+                               p = False;
+                       }
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a SAMR Query User Groups
+****************************************************************************/
+BOOL do_samr_query_usergroups(struct cli_state *cli, 
+                               POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_QUERY_USERGROUPS q_o;
+    BOOL valid_query = False;
+
+       /* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Query User Groups.\n"));
+
+       if (pol == NULL || gid == NULL || num_groups == 0) return False;
+
+       /* store the parameters */
+       make_samr_q_query_usergroups(&q_o, pol);
+
+       /* turn parameters into data stream */
+       samr_io_q_query_usergroups("", &q_o,  &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &data, &rdata))
+       {
+               SAMR_R_QUERY_USERGROUPS r_o;
+               BOOL p;
+
+               /* get user info */
+               r_o.gid = gid;
+
+               samr_io_r_query_usergroups("", &r_o, &rdata, 0);
+               p = rdata.offset != 0;
+               
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p && r_o.ptr_0 != 0)
+               {
+                       valid_query = True;
+                       *num_groups = r_o.num_entries;
+               }
+
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a SAMR Query User Info
+****************************************************************************/
+BOOL do_samr_query_userinfo(struct cli_state *cli, 
+                               POLICY_HND *pol, uint16 switch_value, void* usr)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_QUERY_USERINFO q_o;
+    BOOL valid_query = False;
+
+       /* create and send a MSRPC command with api SAMR_QUERY_USERINFO */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Query User Info.  level: %d\n", switch_value));
+
+       if (pol == NULL || usr == NULL || switch_value == 0) return False;
+
+       /* store the parameters */
+       make_samr_q_query_userinfo(&q_o, pol, switch_value);
+
+       /* turn parameters into data stream */
+       samr_io_q_query_userinfo("", &q_o,  &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &data, &rdata))
+       {
+               SAMR_R_QUERY_USERINFO r_o;
+               BOOL p;
+
+               /* get user info */
+               r_o.info.id = usr;
+
+               samr_io_r_query_userinfo("", &r_o, &rdata, 0);
+               p = rdata.offset != 0;
+               
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p && r_o.switch_value != switch_value)
+               {
+                       DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n",
+                                 r_o.switch_value));
+               }
+
+               if (p && r_o.ptr != 0)
+               {
+                       valid_query = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_query;
+}
+
+/****************************************************************************
+do a SAMR Close
+****************************************************************************/
+BOOL do_samr_close(struct cli_state *cli, POLICY_HND *hnd)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_CLOSE_HND q_c;
+    BOOL valid_close = False;
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       if (hnd == NULL) return False;
+
+       /* create and send a MSRPC command with api SAMR_CLOSE_HND */
+
+       DEBUG(4,("SAMR Close\n"));
+
+       /* store the parameters */
+       make_samr_q_close_hnd(&q_c, hnd);
+
+       /* turn parameters into data stream */
+       samr_io_q_close_hnd("", &q_c,  &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &data, &rdata))
+       {
+               SAMR_R_CLOSE_HND r_c;
+               BOOL p;
+
+               samr_io_r_close_hnd("", &r_c, &rdata, 0);
+               p = rdata.offset != 0;
+
+               if (p && r_c.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_CLOSE_HND: %s\n", get_nt_error_msg(r_c.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       /* check that the returned policy handle is all zeros */
+                       int i;
+                       valid_close = True;
+
+                       for (i = 0; i < sizeof(r_c.pol.data); i++)
+                       {
+                               if (r_c.pol.data[i] != 0)
+                               {
+                                       valid_close = False;
+                                       break;
+                               }
+                       }       
+                       if (!valid_close)
+                       {
+                               DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n"));
+                       }
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_close;
+}
+
index 87225ae326d81eb0f15da8aa25944b11e889840a..d42a2985f0937ba255a0c396dbf259cc522f98da 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* removed in SAMBA_2_0 branch. */
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/****************************************************************************
+do a server net conn enum
+****************************************************************************/
+BOOL do_srv_net_srv_conn_enum(struct cli_state *cli,
+                       char *server_name, char *qual_name,
+                       uint32 switch_value, SRV_CONN_INFO_CTR *ctr,
+                       uint32 preferred_len,
+                       ENUM_HND *hnd)
+{
+       prs_struct data; 
+       prs_struct rdata;
+       SRV_Q_NET_CONN_ENUM q_o;
+    BOOL valid_enum = False;
+
+       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+       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_NETCONNENUM */
+
+       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;
+
+       /* store the parameters */
+       make_srv_q_net_conn_enum(&q_o, server_name, qual_name,
+                                switch_value, ctr,
+                                preferred_len,
+                                hnd);
+
+       /* turn parameters into data stream */
+       srv_io_q_net_conn_enum("", &q_o, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SRV_NETCONNENUM, &data, &rdata))
+       {
+               SRV_R_NET_CONN_ENUM r_o;
+               BOOL p;
+
+               r_o.ctr = ctr;
+
+               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;
+               }
+
+               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;
+               }
+
+               if (p)
+               {
+                       /* ok, at last: we're happy. */
+                       valid_enum = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+       
+       return valid_enum;
+}
+
+/****************************************************************************
+do a server net sess enum
+****************************************************************************/
+BOOL do_srv_net_srv_sess_enum(struct cli_state *cli,
+                       char *server_name, char *qual_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;
+
+       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+       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 */
+
+       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;
+
+       /* store the parameters */
+       make_srv_q_net_sess_enum(&q_o, server_name, qual_name,
+                                switch_value, ctr,
+                                preferred_len,
+                                hnd);
+
+       /* turn parameters into data stream */
+       srv_io_q_net_sess_enum("", &q_o, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SRV_NETSESSENUM, &data, &rdata))
+       {
+               SRV_R_NET_SESS_ENUM r_o;
+               BOOL p;
+
+               r_o.ctr = ctr;
+
+               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;
+               }
+
+               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 (p)
+               {
+                       /* ok, at last: we're happy. */
+                       valid_enum = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+       
+       return valid_enum;
+}
+
+/****************************************************************************
+do a server net share enum
+****************************************************************************/
+BOOL do_srv_net_srv_share_enum(struct cli_state *cli,
+                       char *server_name, 
+                       uint32 switch_value, SRV_SHARE_INFO_CTR *ctr,
+                       uint32 preferred_len,
+                       ENUM_HND *hnd)
+{
+       prs_struct data; 
+       prs_struct rdata;
+       SRV_Q_NET_SHARE_ENUM q_o;
+    BOOL valid_enum = False;
+
+       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+       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_NETSHAREENUM */
+
+       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;
+
+       ctr->switch_value = switch_value;
+       ctr->ptr_share_ctr = 1;
+       ctr->share.info1.num_entries_read = 0;
+       ctr->share.info1.ptr_share_info    = 1;
+
+       /* store the parameters */
+       make_srv_q_net_share_enum(&q_o, server_name, 
+                                switch_value, ctr,
+                                preferred_len,
+                                hnd);
+
+       /* turn parameters into data stream */
+       srv_io_q_net_share_enum("", &q_o, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SRV_NETSHAREENUM, &data, &rdata))
+       {
+               SRV_R_NET_SHARE_ENUM r_o;
+               BOOL p;
+
+               r_o.ctr = ctr;
+
+               srv_io_r_net_share_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;
+               }
+
+               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;
+               }
+
+               if (p)
+               {
+                       /* ok, at last: we're happy. */
+                       valid_enum = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+       
+       return valid_enum;
+}
+
+/****************************************************************************
+do a server net file enum
+****************************************************************************/
+BOOL do_srv_net_srv_file_enum(struct cli_state *cli,
+                       char *server_name, char *qual_name,
+                       uint32 switch_value, SRV_FILE_INFO_CTR *ctr,
+                       uint32 preferred_len,
+                       ENUM_HND *hnd)
+{
+       prs_struct data; 
+       prs_struct rdata;
+       SRV_Q_NET_FILE_ENUM q_o;
+    BOOL valid_enum = False;
+
+       if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+       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_NETFILEENUM */
+
+       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;
+
+       ctr->switch_value = switch_value;
+       ctr->ptr_file_ctr = 1;
+       ctr->file.info3.num_entries_read = 0;
+       ctr->file.info3.ptr_file_info    = 1;
+
+       /* store the parameters */
+       make_srv_q_net_file_enum(&q_o, server_name, qual_name,
+                                switch_value, ctr,
+                                preferred_len,
+                                hnd);
+
+       /* turn parameters into data stream */
+       srv_io_q_net_file_enum("", &q_o, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SRV_NETFILEENUM, &data, &rdata))
+       {
+               SRV_R_NET_FILE_ENUM r_o;
+               BOOL p;
+
+               r_o.ctr = ctr;
+
+               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;
+               }
+
+               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;
+               }
+
+               if (p)
+               {
+                       /* ok, at last: we're happy. */
+                       valid_enum = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+       
+       return valid_enum;
+}
+
+/****************************************************************************
+do a server get info 
+****************************************************************************/
+BOOL do_srv_net_srv_get_info(struct cli_state *cli,
+                       char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr)
+{
+       prs_struct data; 
+       prs_struct rdata;
+       SRV_Q_NET_SRV_GET_INFO q_o;
+    BOOL valid_info = False;
+
+       if (server_name == NULL || switch_value == 0 || ctr == NULL) return False;
+
+       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_NET_SRV_GET_INFO */
+
+       DEBUG(4,("SRV Get Server Info (%s), level %d\n", server_name, switch_value));
+
+       /* store the parameters */
+       make_srv_q_net_srv_get_info(&q_o, server_name, switch_value);
+
+       /* turn parameters into data stream */
+       srv_io_q_net_srv_get_info("", &q_o, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, SRV_NET_SRV_GET_INFO, &data, &rdata))
+       {
+               SRV_R_NET_SRV_GET_INFO r_o;
+               BOOL p;
+
+               r_o.ctr = ctr;
+
+               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;
+               }
+
+               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;
+               }
+
+               if (p)
+               {
+                       /* ok, at last: we're happy. */
+                       valid_info = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+       
+       return valid_info;
+}
+
index 87225ae326d81eb0f15da8aa25944b11e889840a..e45016c1b87e484db0b8e9ca658f402548a564d2 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* removed in SAMBA_2_0 branch. */
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/****************************************************************************
+do a WKS Open Policy
+****************************************************************************/
+BOOL do_wks_query_info(struct cli_state *cli, 
+                       char *server_name, uint32 switch_value,
+                       WKS_INFO_100 *wks100)
+{
+       prs_struct rbuf;
+       prs_struct buf; 
+       WKS_Q_QUERY_INFO q_o;
+       BOOL valid_info = False;
+
+       if (server_name == 0 || wks100 == NULL) return False;
+
+       prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rbuf, 0   , 4, SAFETY_MARGIN, True );
+
+       /* create and send a MSRPC command with api WKS_QUERY_INFO */
+
+       DEBUG(4,("WKS Query Info\n"));
+
+       /* store the parameters */
+       make_wks_q_query_info(&q_o, server_name, switch_value);
+
+       /* turn parameters into data stream */
+       wks_io_q_query_info("", &q_o, &buf, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, WKS_QUERY_INFO, &buf, &rbuf))
+       {
+               WKS_R_QUERY_INFO r_o;
+               BOOL p;
+
+               r_o.wks100 = wks100;
+
+               wks_io_r_query_info("", &r_o, &rbuf, 0);
+               p = rbuf.offset != 0;
+
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("WKS_R_QUERY_INFO: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p)
+               {
+                       valid_info = True;
+               }
+       }
+
+       prs_mem_free(&rbuf);
+       prs_mem_free(&buf );
+
+       return valid_info;
+}
+
index 79b0a812772fdc4828828f438293cf4f611f6f82..a5c523fdb66e59cbc88bb1e32a5b7ac3697ed1e2 100644 (file)
 
 extern int DEBUGLEVEL;
 
+static void lsa_io_trans_names(char *desc, LSA_TRANS_NAME_ENUM *trn, prs_struct *ps, int depth);
+
+/*******************************************************************
+creates a LSA_TRANS_NAME structure.
+********************************************************************/
+void make_lsa_trans_name(LSA_TRANS_NAME *trn, UNISTR2 *uni_name,
+                       uint32 sid_name_use, char *name, uint32 idx)
+{
+       int len_name = strlen(name);
+
+       trn->sid_name_use = sid_name_use;
+       make_uni_hdr(&(trn->hdr_name), len_name, len_name, len_name != 0);
+       make_unistr2(uni_name, name, len_name);
+       trn->domain_idx = idx;
+}
+
+/*******************************************************************
+reads or writes a LSA_TRANS_NAME structure.
+********************************************************************/
+static void lsa_io_trans_name(char *desc, LSA_TRANS_NAME *trn, prs_struct *ps, int depth)
+{
+       if (trn == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_trans_name");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("sid_name_use", ps, depth, &(trn->sid_name_use));
+       smb_io_unihdr ("hdr_name", &(trn->hdr_name), ps, depth);
+       prs_uint32("domain_idx  ", ps, depth, &(trn->domain_idx  ));
+}
+
+/*******************************************************************
+reads or writes a DOM_R_REF structure.
+********************************************************************/
+static void lsa_io_dom_r_ref(char *desc,  DOM_R_REF *r_r, prs_struct *ps, int depth)
+{
+       int i, s, n;
+
+       prs_debug(ps, depth, desc, "smb_io_dom_r_ref");
+       depth++;
+
+       if (r_r == NULL) return;
+
+       prs_align(ps);
+       
+       prs_uint32("undoc_buffer  ", ps, depth, &(r_r->undoc_buffer  )); /* undocumented buffer pointer. */
+       prs_uint32("num_ref_doms_1", ps, depth, &(r_r->num_ref_doms_1)); /* num referenced domains? */
+       prs_uint32("undoc_buffer2 ", ps, depth, &(r_r->undoc_buffer2 )); /* undocumented buffer pointer. */
+       prs_uint32("max_entries   ", ps, depth, &(r_r->max_entries   )); /* 32 - max number of entries */
+       prs_uint32("num_ref_doms_2", ps, depth, &(r_r->num_ref_doms_2)); /* 4 - num referenced domains? */
+
+       SMB_ASSERT_ARRAY(r_r->hdr_ref_dom, r_r->num_ref_doms_1-1);
+       SMB_ASSERT_ARRAY(r_r->ref_dom, r_r->num_ref_doms_2);
+
+       for (i = 0; i < r_r->num_ref_doms_1; i++)
+       {
+               fstring t;
+
+               slprintf(t, sizeof(t) - 1, "dom_ref[%d] ", i);
+               smb_io_unihdr(t, &(r_r->hdr_ref_dom[i].hdr_dom_name), ps, depth);
+
+               slprintf(t, sizeof(t) - 1, "sid_ptr[%d] ", i);
+               prs_uint32(t, ps, depth, &(r_r->hdr_ref_dom[i].ptr_dom_sid));
+       }
+
+       for (i = 0, n = 0, s = 0; i < r_r->num_ref_doms_2; i++)
+       {
+               fstring t;
+
+               if (r_r->hdr_ref_dom[i].hdr_dom_name.buffer != 0)
+               {
+                       slprintf(t, sizeof(t) - 1, "dom_ref[%d] ", i);
+                       smb_io_unistr2(t, &(r_r->ref_dom[n].uni_dom_name), True, ps, depth); /* domain name unicode string */
+                       n++;
+               }
+
+               if (r_r->hdr_ref_dom[i].ptr_dom_sid != 0)
+               {
+                       slprintf(t, sizeof(t) - 1, "sid_ptr[%d] ", i);
+                       smb_io_dom_sid2("", &(r_r->ref_dom[s].ref_dom), ps, depth); /* referenced domain SIDs */
+                       s++;
+               }
+       }
+}
+
+
 /*******************************************************************
 makes an LSA_SEC_QOS structure.
 ********************************************************************/
@@ -405,6 +493,244 @@ void lsa_io_r_query(char *desc,  LSA_R_QUERY_INFO *r_q, prs_struct *ps, int dept
        prs_uint32("status", ps, depth, &(r_q->status));
 }
 
+/*******************************************************************
+makes a LSA_SID_ENUM structure.
+********************************************************************/
+void make_lsa_sid_enum(LSA_SID_ENUM *sen, int num_entries, DOM_SID **sids)
+{
+       int i, i2;
+       if (sen == NULL || sids == NULL) return;
+
+       DEBUG(5,("make_lsa_sid_enum\n"));
+
+       sen->num_entries  = num_entries;
+       sen->ptr_sid_enum = num_entries != 0 ? 1 : 0;
+       sen->num_entries2 = num_entries;
+
+       SMB_ASSERT_ARRAY(sen->sid, sen->num_entries);
+
+       for (i = 0, i2 = 0; i < num_entries; i++)
+       {
+               if (sids[i] != NULL)
+               {
+                       sen->ptr_sid[i] = 1;
+                       make_dom_sid2(&(sen->sid[i2]), sids[i]);
+                       i2++;
+               }
+               else
+               {
+                       sen->ptr_sid[i] = 0;
+               }
+       }
+}
+
+/*******************************************************************
+reads or writes a LSA_SID_ENUM structure.
+********************************************************************/
+static void lsa_io_sid_enum(char *desc, LSA_SID_ENUM *sen,
+                               prs_struct *ps, int depth)
+{
+       int i;
+
+       if (sen == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_sid_enum");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("num_entries ", ps, depth, &(sen->num_entries));
+       prs_uint32("ptr_sid_enum", ps, depth, &(sen->ptr_sid_enum)); 
+       prs_uint32("num_entries2", ps, depth, &(sen->num_entries2)); 
+
+       SMB_ASSERT_ARRAY(sen->ptr_sid, sen->num_entries);
+
+       for (i = 0; i < sen->num_entries; i++)
+       {       
+               fstring temp;
+               slprintf(temp, sizeof(temp) - 1, "ptr_sid[%d]", i);
+               prs_uint32(temp, ps, depth, &(sen->ptr_sid[i])); /* domain SID pointers to be looked up. */
+       }
+
+       SMB_ASSERT_ARRAY(sen->sid, sen->num_entries);
+
+       for (i = 0; i < sen->num_entries; i++)
+       {
+               fstring temp;
+               slprintf(temp, sizeof(temp) - 1, "sid[%d]", i);
+               smb_io_dom_sid2(temp, &(sen->sid[i]), ps, depth); /* domain SIDs to be looked up. */
+       }
+}
+
+/*******************************************************************
+makes an LSA_R_ENUM_TRUST_DOM structure.
+********************************************************************/
+void make_q_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, POLICY_HND *hnd,
+                               int num_sids, DOM_SID **sids,
+                               uint16 level)
+{
+       if (q_l == NULL) return;
+
+       DEBUG(5,("make_r_enum_trust_dom\n"));
+
+       memcpy(&(q_l->pol), hnd, sizeof(q_l->pol));
+       make_lsa_sid_enum(&(q_l->sids), num_sids, sids);
+
+       q_l->names.num_entries     = 0;
+       q_l->names.ptr_trans_names = 0;
+       q_l->names.num_entries2    = 0;
+
+       q_l->level.value = level;
+}
+
+/*******************************************************************
+reads or writes a LSA_Q_LOOKUP_SIDS structure.
+********************************************************************/
+void lsa_io_q_lookup_sids(char *desc, LSA_Q_LOOKUP_SIDS *q_s, prs_struct *ps, int depth)
+{
+       if (q_s == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_q_lookup_sids");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd     ("pol_hnd", &(q_s->pol), ps, depth); /* policy handle */
+       lsa_io_sid_enum    ("sids   ", &(q_s->sids   ), ps, depth); /* sids to be looked up */
+       lsa_io_trans_names ("names  ", &(q_s->names  ), ps, depth); /* translated names */
+       smb_io_lookup_level("switch ", &(q_s->level  ), ps, depth); /* lookup level */
+
+       prs_uint32("mapped_count", ps, depth, &(q_s->mapped_count));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void lsa_io_trans_names(char *desc, LSA_TRANS_NAME_ENUM *trn,
+                               prs_struct *ps, int depth)
+{
+       int i;
+       int i2;
+
+       if (trn == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_trans_names");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("num_entries    ", ps, depth, &(trn->num_entries));
+       prs_uint32("ptr_trans_names", ps, depth, &(trn->ptr_trans_names));
+
+       if (trn->ptr_trans_names != 0)
+       {
+               prs_uint32("num_entries2   ", ps, depth, &(trn->num_entries2));
+
+               SMB_ASSERT_ARRAY(trn->name, trn->num_entries);
+
+               for (i = 0, i2 = 0; i < trn->num_entries2; i++)
+               {
+                       fstring t;
+                       slprintf(t, sizeof(t) - 1, "name[%d] ", i);
+
+                       lsa_io_trans_name(t, &(trn->name[i]), ps, depth); /* translated name */
+
+                       if (trn->name[i].hdr_name.buffer != 0)
+                       {
+                               smb_io_unistr2(t, &(trn->uni_name[i2]), 1, ps, depth);
+                               prs_align(ps);
+                               i2++;
+                       }
+               }
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void lsa_io_r_lookup_sids(char *desc,  LSA_R_LOOKUP_SIDS *r_s, prs_struct *ps, int depth)
+{
+       if (r_s == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_r_lookup_sids");
+       depth++;
+
+       prs_align(ps);
+       
+       lsa_io_dom_r_ref  ("dom_ref", r_s->dom_ref, ps, depth); /* domain reference info */
+       lsa_io_trans_names("names  ", r_s->names  , ps, depth); /* translated names */
+
+       prs_align(ps);
+
+       prs_uint32("mapped_count", ps, depth, &(r_s->mapped_count));
+
+       prs_uint32("status      ", ps, depth, &(r_s->status));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void lsa_io_q_lookup_rids(char *desc,  LSA_Q_LOOKUP_RIDS *q_r, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (q_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_q_lookup_rids");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(q_r->pol), ps, depth); /* policy handle */
+
+       prs_uint32("num_entries    ", ps, depth, &(q_r->num_entries));
+       prs_uint32("num_entries2   ", ps, depth, &(q_r->num_entries2));
+       prs_uint32("buffer_dom_sid ", ps, depth, &(q_r->buffer_dom_sid)); /* undocumented domain SID buffer pointer */
+       prs_uint32("buffer_dom_name", ps, depth, &(q_r->buffer_dom_name)); /* undocumented domain name buffer pointer */
+
+       SMB_ASSERT_ARRAY(q_r->lookup_name, q_r->num_entries);
+
+       for (i = 0; i < q_r->num_entries; i++)
+       {
+               smb_io_unistr3("", &(q_r->lookup_name[i]), ps, depth); /* names to be looked up */
+       }
+
+       prs_uint8s (False, "undoc          ", ps, depth, q_r->undoc, UNKNOWN_LEN);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void lsa_io_r_lookup_rids(char *desc,  LSA_R_LOOKUP_RIDS *r_r, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_r_lookup_rids");
+       depth++;
+
+       prs_align(ps);
+       
+       lsa_io_dom_r_ref("", &(r_r->dom_ref), ps, depth); /* domain reference info */
+
+       prs_uint32("num_entries ", ps, depth, &(r_r->num_entries));
+       prs_uint32("undoc_buffer", ps, depth, &(r_r->undoc_buffer));
+       prs_uint32("num_entries2", ps, depth, &(r_r->num_entries2));
+
+       SMB_ASSERT_ARRAY(r_r->dom_rid, r_r->num_entries2);
+
+       for (i = 0; i < r_r->num_entries2; i++)
+       {
+               smb_io_dom_rid2("", &(r_r->dom_rid[i]), ps, depth); /* domain RIDs being looked up */
+       }
+
+       prs_uint32("num_entries3", ps, depth, &(r_r->num_entries3));
+
+       prs_uint32("status      ", ps, depth, &(r_r->status));
+}
+
+
 /*******************************************************************
 makes an LSA_Q_CLOSE structure.
 ********************************************************************/
index 3e734d7edb11930834ffb92558f98a2b36e3bca3..f564ac1dd4338477a515ddd83bbe406d8dc2cba8 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* removed in SAMBA_2_0 branch. */
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_open_hklm(REG_Q_OPEN_HKLM *q_o,
+                               uint16 unknown_0, uint32 level)
+{
+       q_o->ptr = 1;
+       q_o->unknown_0 = unknown_0;
+       q_o->unknown_1 = 0x0; /* random - changes */
+       q_o->level = level;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_open_hklm(char *desc,  REG_Q_OPEN_HKLM *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_open_hklm");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("ptr      ", ps, depth, &(r_q->ptr      ));
+       if (r_q->ptr != 0)
+       {
+               prs_uint16("unknown_0", ps, depth, &(r_q->unknown_0));
+               prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1));
+               prs_uint32("level    ", ps, depth, &(r_q->level    ));
+       }
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_open_hklm(char *desc,  REG_R_OPEN_HKLM *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_open_hklm");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_r->pol), ps, depth);
+
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_flush_key(REG_Q_FLUSH_KEY *q_u, POLICY_HND *pol)
+{
+       memcpy(&(q_u->pol), pol, sizeof(q_u->pol));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_flush_key(char *desc,  REG_Q_FLUSH_KEY *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_flush_key");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pol), ps, depth);
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_flush_key(char *desc,  REG_R_FLUSH_KEY *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_flush_key");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+/*******************************************************************
+reads or writes SEC_DESC_BUF and SEC_DATA structures.
+********************************************************************/
+static void reg_io_hdrbuf_sec(uint32 ptr, uint32 *ptr3, BUFHDR *hdr_sec, SEC_DESC_BUF *data, prs_struct *ps, int depth)
+{
+       if (ptr != 0)
+       {
+               uint32 hdr_offset;
+               uint32 old_offset;
+               smb_io_hdrbuf_pre("hdr_sec", hdr_sec, ps, depth, &hdr_offset);
+               old_offset = ps->offset;
+               if (ptr3 != NULL)
+               {
+                       prs_uint32("ptr3", ps, depth, ptr3);
+               }
+               if (ptr3 == NULL || *ptr3 != 0)
+               {
+                       sec_io_desc_buf("data   ", &data   , ps, depth); /* JRA - this line is probably wrong... */
+               }
+               smb_io_hdrbuf_post("hdr_sec", hdr_sec, ps, depth, hdr_offset,
+                                  data->max_len, data->len);
+               ps->offset = old_offset + data->len + sizeof(uint32) * ((ptr3 != NULL) ? 5 : 3);
+               prs_align(ps);
+       }
+}
+
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_create_key(REG_Q_CREATE_KEY *q_c, POLICY_HND *hnd,
+                               char *name, char *class, SEC_ACCESS *sam_access,
+                               SEC_DESC_BUF *sec_buf)
+{
+       int len_name  = name  != NULL ? strlen(name ) + 1: 0;
+       int len_class = class != NULL ? strlen(class) + 1: 0;
+
+       ZERO_STRUCTP(q_c);
+
+       memcpy(&(q_c->pnt_pol), hnd, sizeof(q_c->pnt_pol));
+
+       make_uni_hdr(&(q_c->hdr_name), len_name, len_name, 1);
+       make_unistr2(&(q_c->uni_name), name, len_name);
+
+       make_uni_hdr(&(q_c->hdr_class), len_class, len_class, 1);
+       make_unistr2(&(q_c->uni_class), class, len_class);
+
+       q_c->reserved = 0x00000000;
+       memcpy(&(q_c->sam_access), sam_access, sizeof(q_c->sam_access));
+
+       q_c->ptr1 = 1;
+       q_c->sec_info = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
+
+       q_c->data = sec_buf;
+       q_c->ptr2 = 1;
+       make_buf_hdr(&(q_c->hdr_sec), sec_buf->len, sec_buf->len);
+       q_c->ptr3 = 1;
+       q_c->unknown_2 = 0x00000000;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_create_key(char *desc,  REG_Q_CREATE_KEY *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_create_key");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pnt_pol), ps, depth);
+
+       smb_io_unihdr ("", &(r_q->hdr_name), ps, depth);
+       smb_io_unistr2("", &(r_q->uni_name), r_q->hdr_name.buffer, ps, depth);
+       prs_align(ps);
+
+       smb_io_unihdr ("", &(r_q->hdr_class), ps, depth);
+       smb_io_unistr2("", &(r_q->uni_class), r_q->hdr_class.buffer, ps, depth);
+       prs_align(ps);
+
+       prs_uint32("reserved", ps, depth, &(r_q->reserved));
+       sec_io_access("sam_access", &r_q->sam_access, ps, depth);
+
+       prs_uint32("ptr1", ps, depth, &(r_q->ptr1));
+       if (r_q->ptr1 != 0)
+       {
+               prs_uint32("sec_info", ps, depth, &(r_q->sec_info));
+       }
+
+       prs_uint32("ptr2", ps, depth, &(r_q->ptr2));
+       reg_io_hdrbuf_sec(r_q->ptr2, &r_q->ptr3, &r_q->hdr_sec, r_q->data, ps, depth);
+
+       prs_uint32("unknown_2", ps, depth, &(r_q->unknown_2));
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_create_key(char *desc,  REG_R_CREATE_KEY *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_create_key");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_r->key_pol), ps, depth);
+       prs_uint32("unknown", ps, depth, &(r_r->unknown));
+
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_delete_val(REG_Q_DELETE_VALUE *q_c, POLICY_HND *hnd,
+                               char *name)
+{
+       int len_name  = name  != NULL ? strlen(name ) + 1: 0;
+       ZERO_STRUCTP(q_c);
+
+       memcpy(&(q_c->pnt_pol), hnd, sizeof(q_c->pnt_pol));
+
+       make_uni_hdr(&(q_c->hdr_name), len_name, len_name, 1);
+       make_unistr2(&(q_c->uni_name), name, len_name);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_delete_val(char *desc,  REG_Q_DELETE_VALUE *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_delete_val");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pnt_pol), ps, depth);
+
+       smb_io_unihdr ("", &(r_q->hdr_name), ps, depth);
+       smb_io_unistr2("", &(r_q->uni_name), r_q->hdr_name.buffer, ps, depth);
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_delete_val(char *desc,  REG_R_DELETE_VALUE *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_delete_val");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_delete_key(REG_Q_DELETE_KEY *q_c, POLICY_HND *hnd,
+                               char *name)
+{
+       int len_name  = name  != NULL ? strlen(name ) + 1: 0;
+       ZERO_STRUCTP(q_c);
+
+       memcpy(&(q_c->pnt_pol), hnd, sizeof(q_c->pnt_pol));
+
+       make_uni_hdr(&(q_c->hdr_name), len_name, len_name, 1);
+       make_unistr2(&(q_c->uni_name), name, len_name);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_delete_key(char *desc,  REG_Q_DELETE_KEY *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_delete_key");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pnt_pol), ps, depth);
+
+       smb_io_unihdr ("", &(r_q->hdr_name), ps, depth);
+       smb_io_unistr2("", &(r_q->uni_name), r_q->hdr_name.buffer, ps, depth);
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_delete_key(char *desc,  REG_R_DELETE_KEY *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_delete_key");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_query_key(REG_Q_QUERY_KEY *q_o, POLICY_HND *hnd,
+                               uint32 max_class_len)
+{
+       ZERO_STRUCTP(q_o);
+
+       memcpy(&(q_o->pol), hnd, sizeof(q_o->pol));
+       make_uni_hdr(&q_o->hdr_class, max_class_len, 0, max_class_len > 0 ? 1 : 0);
+       q_o->uni_class.uni_max_len = max_class_len;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_query_key(char *desc,  REG_Q_QUERY_KEY *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_query_key");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pol), ps, depth);
+       smb_io_unihdr ("", &(r_q->hdr_class), ps, depth);
+       smb_io_unistr2("", &(r_q->uni_class), r_q->hdr_class.buffer, ps, depth);
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_query_key(char *desc,  REG_R_QUERY_KEY *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_query_key");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_unihdr ("", &(r_r->hdr_class), ps, depth);
+       smb_io_unistr2("", &(r_r->uni_class), r_r->hdr_class.buffer, ps, depth);
+
+       prs_align(ps);
+
+       prs_uint32("num_subkeys   ", ps, depth, &(r_r->num_subkeys   ));
+       prs_uint32("max_subkeylen ", ps, depth, &(r_r->max_subkeylen ));
+       prs_uint32("mak_subkeysize", ps, depth, &(r_r->max_subkeysize));
+       prs_uint32("num_values    ", ps, depth, &(r_r->num_values    ));
+       prs_uint32("max_valnamelen", ps, depth, &(r_r->max_valnamelen));
+       prs_uint32("max_valbufsize", ps, depth, &(r_r->max_valbufsize));
+       prs_uint32("sec_desc      ", ps, depth, &(r_r->sec_desc      ));
+       smb_io_time("mod_time     ", &(r_r->mod_time), ps, depth);
+       
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_unk_1a(REG_Q_UNK_1A *q_o, POLICY_HND *hnd)
+{
+       memcpy(&(q_o->pol), hnd, sizeof(q_o->pol));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_unk_1a(char *desc,  REG_Q_UNK_1A *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_unk_1a");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pol), ps, depth);
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_unk_1a(char *desc,  REG_R_UNK_1A *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_unk_1a");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("unknown", ps, depth, &(r_r->unknown));
+       prs_uint32("status" , ps, depth, &(r_r->status ));
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_q_open_hku(REG_Q_OPEN_HKU *q_o,
+                               uint16 unknown_0, uint32 level)
+{
+       q_o->ptr = 1;
+       q_o->unknown_0 = unknown_0;
+       q_o->unknown_1 = 0x0; /* random - changes */
+       q_o->level = level;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_open_hku(char *desc,  REG_Q_OPEN_HKU *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_open_hku");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("ptr      ", ps, depth, &(r_q->ptr      ));
+       if (r_q->ptr != 0)
+       {
+               prs_uint16("unknown_0", ps, depth, &(r_q->unknown_0));
+               prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1));
+               prs_uint32("level    ", ps, depth, &(r_q->level    ));
+       }
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_open_hku(char *desc,  REG_R_OPEN_HKU *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_open_hku");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_r->pol), ps, depth);
+
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+
+/*******************************************************************
+makes an REG_Q_CLOSE structure.
+********************************************************************/
+void make_reg_q_close(REG_Q_CLOSE *q_c, POLICY_HND *hnd)
+{
+       if (q_c == NULL || hnd == NULL) return;
+
+       DEBUG(5,("make_reg_q_close\n"));
+
+       memcpy(&(q_c->pol), hnd, sizeof(q_c->pol));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_close(char *desc,  REG_Q_CLOSE *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_unknown_1");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_close(char *desc,  REG_R_CLOSE *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_unknown_1");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("", &(r_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_reg_q_set_key_sec(REG_Q_SET_KEY_SEC *q_i, POLICY_HND *pol, SEC_DESC_BUF *sec_desc_buf)
+{
+       if (q_i == NULL) return;
+
+       memcpy(&(q_i->pol), pol, sizeof(q_i->pol));
+
+       q_i->sec_info = DACL_SECURITY_INFORMATION;
+
+       q_i->ptr = 1;
+       make_buf_hdr(&(q_i->hdr_sec), sec_desc_buf->len, sec_desc_buf->len);
+       q_i->data = sec_desc_buf;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_set_key_sec(char *desc,  REG_Q_SET_KEY_SEC *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_set_key_sec");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pol), ps, depth); 
+
+       prs_uint32("sec_info", ps, depth, &(r_q->sec_info));
+       prs_uint32("ptr    ", ps, depth, &(r_q->ptr    ));
+
+       reg_io_hdrbuf_sec(r_q->ptr, NULL, &r_q->hdr_sec, r_q->data, ps, depth);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_set_key_sec(char *desc, REG_R_SET_KEY_SEC *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_set_key_sec");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("status", ps, depth, &(r_q->status));
+}
+
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_reg_q_get_key_sec(REG_Q_GET_KEY_SEC *q_i, POLICY_HND *pol, 
+                               uint32 sec_buf_size, SEC_DESC_BUF *psdb)
+{
+       if (q_i == NULL) return;
+
+       memcpy(&(q_i->pol), pol, sizeof(q_i->pol));
+
+       q_i->sec_info = OWNER_SECURITY_INFORMATION |
+                       GROUP_SECURITY_INFORMATION |
+                       DACL_SECURITY_INFORMATION;
+
+       q_i->ptr = psdb != NULL ? 1 : 0;
+       q_i->data = psdb;
+
+       make_buf_hdr(&(q_i->hdr_sec), sec_buf_size, 0);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_get_key_sec(char *desc,  REG_Q_GET_KEY_SEC *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_get_key_sec");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pol), ps, depth); 
+
+       prs_uint32("sec_info", ps, depth, &(r_q->sec_info));
+       prs_uint32("ptr     ", ps, depth, &(r_q->ptr     ));
+
+       reg_io_hdrbuf_sec(r_q->ptr, NULL, &r_q->hdr_sec, r_q->data, ps, depth);
+}
+
+#if 0
+/*******************************************************************
+makes a structure.
+********************************************************************/
+ void make_reg_r_get_key_sec(REG_R_GET_KEY_SEC *r_i, POLICY_HND *pol, 
+                               uint32 buf_len, uint8 *buf,
+                               uint32 status)
+{
+       if (r_i == NULL) return;
+
+       r_i->ptr = 1;
+       make_buf_hdr(&(r_i->hdr_sec), buf_len, buf_len);
+       make_sec_desc_buf(r_i->data, buf_len, 1);
+
+       r_i->status = status; /* 0x0000 0000 or 0x0000 007a */
+}
+#endif 
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_get_key_sec(char *desc,  REG_R_GET_KEY_SEC *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_get_key_sec");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("ptr      ", ps, depth, &(r_q->ptr      ));
+
+       if (r_q->ptr != 0)
+       {
+               smb_io_hdrbuf("", &(r_q->hdr_sec), ps, depth);
+               sec_io_desc_buf("", &r_q->data, ps, depth);
+               prs_align(ps);
+       }
+
+       prs_uint32("status", ps, depth, &(r_q->status));
+}
+
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, char *product_type,
+                               time_t unix_time, uint8 major, uint8 minor)
+{
+       int len_type  = strlen(product_type);
+
+       if (q_i == NULL) return;
+
+       memcpy(&(q_i->pol), pol, sizeof(q_i->pol));
+
+       make_uni_hdr(&(q_i->hdr_type), len_type, len_type, 1);
+       make_unistr2(&(q_i->uni_type), product_type, len_type);
+
+       q_i->ptr1 = 1;
+       unix_to_nt_time(&(q_i->time), unix_time);
+       q_i->major_version1 = major;
+       q_i->minor_version1 = minor;
+       memset(q_i->pad1, 0, sizeof(q_i->pad1));
+
+       q_i->ptr2 = 1;
+       q_i->major_version2 = major;
+       q_i->minor_version2 = minor;
+       memset(q_i->pad2, 0, sizeof(q_i->pad2));
+
+       q_i->ptr3 = 1;
+       q_i->unknown = 0x00000000;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_info(char *desc,  REG_Q_INFO *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_info");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pol), ps, depth); 
+       smb_io_unihdr ("", &(r_q->hdr_type), ps, depth);
+       smb_io_unistr2("", &(r_q->uni_type), r_q->hdr_type.buffer, ps, depth);
+
+       prs_align(ps);
+       
+       prs_uint32("ptr1", ps, depth, &(r_q->ptr1));
+
+       if (r_q->ptr1 != 0)
+       {
+               smb_io_time("", &(r_q->time), ps, depth);
+               prs_uint8 ("major_version1", ps, depth, &(r_q->major_version1));
+               prs_uint8 ("minor_version1", ps, depth, &(r_q->minor_version1));
+               prs_uint8s(False, "pad1", ps, depth, r_q->pad1, sizeof(r_q->pad1));
+       }
+
+       prs_uint32("ptr2", ps, depth, &(r_q->ptr2));
+
+       if (r_q->ptr2 != 0)
+       {
+               prs_uint8 ("major_version2", ps, depth, &(r_q->major_version2));
+               prs_uint8 ("minor_version2", ps, depth, &(r_q->minor_version2));
+               prs_uint8s(False, "pad2", ps, depth, r_q->pad2, sizeof(r_q->pad2));
+       }
+
+       prs_uint32("ptr3", ps, depth, &(r_q->ptr3));
+
+       if (r_q->ptr3 != 0)
+       {
+               prs_uint32("unknown", ps, depth, &(r_q->unknown));
+       }
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_r_info(REG_R_INFO *r_r,
+                               uint32 level, char *os_type,
+                               uint32 unknown_0, uint32 unknown_1,
+                               uint32 status)
+{
+       uint8 buf[512];
+       int len = struni2((char *)buf, os_type);
+
+       r_r->ptr1 = 1;
+       r_r->level = level;
+
+       r_r->ptr_type = 1;
+       make_buffer2(&(r_r->uni_type), buf, len*2);
+
+       r_r->ptr2 = 1;
+       r_r->unknown_0 = unknown_0;
+
+       r_r->ptr3 = 1;
+       r_r->unknown_1 = unknown_1;
+
+       r_r->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_info");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("ptr1", ps, depth, &(r_r->ptr1));
+
+       if (r_r->ptr1 != 0)
+       {
+               prs_uint32("level", ps, depth, &(r_r->level));
+               prs_uint32("ptr_type", ps, depth, &(r_r->ptr_type));
+
+               smb_io_buffer2("uni_type", &(r_r->uni_type), r_r->ptr_type, ps, depth);
+
+               prs_uint32("ptr2", ps, depth, &(r_r->ptr2));
+
+               if (r_r->ptr2 != 0)
+               {
+                       prs_uint32("unknown_0", ps, depth, &(r_r->unknown_0));
+               }
+
+               prs_uint32("ptr3", ps, depth, &(r_r->ptr3));
+
+               if (r_r->ptr3 != 0)
+               {
+                       prs_uint32("unknown_1", ps, depth, &(r_r->unknown_1));
+               }
+
+       }
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_reg_q_enum_val(REG_Q_ENUM_VALUE *q_i, POLICY_HND *pol,
+                               uint32 val_idx, uint32 max_val_len,
+                               uint32 max_buf_len)
+{
+       if (q_i == NULL) return;
+
+       ZERO_STRUCTP(q_i);
+
+       memcpy(&(q_i->pol), pol, sizeof(q_i->pol));
+
+       q_i->val_index = val_idx;
+       make_uni_hdr(&q_i->hdr_name, max_val_len, 0, 1);
+       q_i->uni_name.uni_max_len = max_val_len;
+       
+       q_i->ptr_type = 1;
+       q_i->type = 0x0;
+
+       q_i->ptr_value = 1;
+       q_i->buf_value.buf_max_len = max_buf_len;
+
+       q_i->ptr1 = 1;
+       q_i->len_value1 = max_buf_len;
+
+       q_i->ptr2 = 1;
+       q_i->len_value2 = 0;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_enum_val(char *desc,  REG_Q_ENUM_VALUE *q_q, prs_struct *ps, int depth)
+{
+       if (q_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_enum_val");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(q_q->pol), ps, depth); 
+       
+       prs_uint32("val_index", ps, depth, &(q_q->val_index));
+       smb_io_unihdr ("hdr_name", &(q_q->hdr_name), ps, depth);
+       smb_io_unistr2("uni_name", &(q_q->uni_name), q_q->hdr_name.buffer, ps, depth);
+       prs_align(ps);
+
+       prs_uint32("ptr_type", ps, depth, &(q_q->ptr_type));
+
+       if (q_q->ptr_type != 0)
+       {
+               prs_uint32("type", ps, depth, &(q_q->type));
+       }
+
+       prs_uint32("ptr_value", ps, depth, &(q_q->ptr_value));
+       smb_io_buffer2("buf_value", &(q_q->buf_value), q_q->ptr_value, ps, depth);
+       prs_align(ps);
+
+       prs_uint32("ptr1", ps, depth, &(q_q->ptr1));
+       if (q_q->ptr1 != 0)
+       {
+               prs_uint32("len_value1", ps, depth, &(q_q->len_value1));
+       }
+       prs_uint32("ptr2", ps, depth, &(q_q->ptr2));
+       if (q_q->ptr2 != 0)
+       {
+               prs_uint32("len_value2", ps, depth, &(q_q->len_value2));
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_enum_val(char *desc,  REG_R_ENUM_VALUE *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_enum_val");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_unihdr ("hdr_name", &(r_q->hdr_name), ps, depth);
+       smb_io_unistr2("uni_name", &(r_q->uni_name), r_q->hdr_name.buffer, ps, depth);
+       prs_align(ps);
+
+       prs_uint32("ptr_type", ps, depth, &(r_q->ptr_type));
+
+       if (r_q->ptr_type != 0)
+       {
+               prs_uint32("type", ps, depth, &(r_q->type));
+       }
+
+       prs_uint32("ptr_value", ps, depth, &(r_q->ptr_value));
+       smb_io_buffer2("buf_value", r_q->buf_value, r_q->ptr_value, ps, depth);
+       prs_align(ps);
+
+       prs_uint32("ptr1", ps, depth, &(r_q->ptr1));
+       if (r_q->ptr1 != 0)
+       {
+               prs_uint32("len_value1", ps, depth, &(r_q->len_value1));
+       }
+
+       prs_uint32("ptr2", ps, depth, &(r_q->ptr2));
+       if (r_q->ptr2 != 0)
+       {
+               prs_uint32("len_value2", ps, depth, &(r_q->len_value2));
+       }
+
+       prs_uint32("status", ps, depth, &(r_q->status));
+}
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_reg_q_create_val(REG_Q_CREATE_VALUE *q_i, POLICY_HND *pol,
+                               char *val_name, uint32 type,
+                               BUFFER3 *val)
+{
+       int val_len = strlen(val_name) + 1;
+
+       if (q_i == NULL) return;
+
+       ZERO_STRUCTP(q_i);
+
+       memcpy(&(q_i->pol), pol, sizeof(q_i->pol));
+
+       make_uni_hdr(&q_i->hdr_name, val_len, val_len, 1);
+       make_unistr2(&(q_i->uni_name), val_name, val_len);
+       
+       q_i->type      = type;
+       q_i->buf_value = val;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_create_val(char *desc,  REG_Q_CREATE_VALUE *q_q, prs_struct *ps, int depth)
+{
+       if (q_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_create_val");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(q_q->pol), ps, depth); 
+       
+       smb_io_unihdr ("hdr_name", &(q_q->hdr_name), ps, depth);
+       smb_io_unistr2("uni_name", &(q_q->uni_name), q_q->hdr_name.buffer, ps, depth);
+       prs_align(ps);
+
+       prs_uint32("type", ps, depth, &(q_q->type));
+       smb_io_buffer3("buf_value", q_q->buf_value, ps, depth);
+       prs_align(ps);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_create_val(char *desc,  REG_R_CREATE_VALUE *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_create_val");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32("status", ps, depth, &(r_q->status));
+}
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_reg_q_enum_key(REG_Q_ENUM_KEY *q_i, POLICY_HND *pol, uint32 key_idx)
+{
+       if (q_i == NULL) return;
+
+       memcpy(&(q_i->pol), pol, sizeof(q_i->pol));
+
+       q_i->key_index = key_idx;
+       q_i->key_name_len = 0;
+       q_i->unknown_1 = 0x0414;
+
+       q_i->ptr1 = 1;
+       q_i->unknown_2 = 0x0000020A;
+       memset(q_i->pad1, 0, sizeof(q_i->pad1));
+
+       q_i->ptr2 = 1;
+       memset(q_i->pad2, 0, sizeof(q_i->pad2));
+
+       q_i->ptr3 = 1;
+       unix_to_nt_time(&q_i->time, 0);            /* current time? */
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_enum_key(char *desc,  REG_Q_ENUM_KEY *q_q, prs_struct *ps, int depth)
+{
+       if (q_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_enum_key");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(q_q->pol), ps, depth); 
+       
+       prs_uint32("key_index", ps, depth, &(q_q->key_index));
+       prs_uint16("key_name_len", ps, depth, &(q_q->key_name_len));
+       prs_uint16("unknown_1", ps, depth, &(q_q->unknown_1));
+
+       prs_uint32("ptr1", ps, depth, &(q_q->ptr1));
+
+       if (q_q->ptr1 != 0)
+       {
+               prs_uint32("unknown_2", ps, depth, &(q_q->unknown_2));
+               prs_uint8s(False, "pad1", ps, depth, q_q->pad1, sizeof(q_q->pad1));
+       }
+
+       prs_uint32("ptr2", ps, depth, &(q_q->ptr2));
+
+       if (q_q->ptr2 != 0)
+       {
+               prs_uint8s(False, "pad2", ps, depth, q_q->pad2, sizeof(q_q->pad2));
+       }
+
+       prs_uint32("ptr3", ps, depth, &(q_q->ptr3));
+
+       if (q_q->ptr3 != 0)
+       {
+               smb_io_time("", &(q_q->time), ps, depth);
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_enum_key(char *desc,  REG_R_ENUM_KEY *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_enum_key");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint16("key_name_len", ps, depth, &(r_q->key_name_len));
+       prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1));
+
+       prs_uint32("ptr1", ps, depth, &(r_q->ptr1));
+
+       if (r_q->ptr1 != 0)
+       {
+               prs_uint32("unknown_2", ps, depth, &(r_q->unknown_2));
+               prs_uint32("unknown_3", ps, depth, &(r_q->unknown_3));
+               smb_io_unistr3("key_name", &(r_q->key_name), ps, depth);
+               prs_align(ps);
+       }
+
+       prs_uint32("ptr2", ps, depth, &(r_q->ptr2));
+
+       if (r_q->ptr2 != 0)
+       {
+               prs_uint8s(False, "pad2", ps, depth, r_q->pad2, sizeof(r_q->pad2));
+       }
+
+       prs_uint32("ptr3", ps, depth, &(r_q->ptr3));
+
+       if (r_q->ptr3 != 0)
+       {
+               smb_io_time("", &(r_q->time), ps, depth);
+       }
+
+       prs_uint32("status", ps, depth, &(r_q->status));
+}
+
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_reg_q_open_entry(REG_Q_OPEN_ENTRY *r_q, POLICY_HND *pol,
+                               char *key_name, uint32 unk)
+{
+       int len_name = strlen(key_name)+1;
+
+       if (r_q == NULL) return;
+
+       memcpy(&(r_q->pol), pol, sizeof(r_q->pol));
+
+       make_uni_hdr(&(r_q->hdr_name), len_name, len_name, 1);
+       make_unistr2(&(r_q->uni_name), key_name, len_name);
+
+       r_q->unknown_0 = 0x00000000;
+       r_q->unknown_1 = unk;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_q_open_entry(char *desc,  REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int depth)
+{
+       if (r_q == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_q_entry");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_q->pol), ps, depth);
+       smb_io_unihdr ("", &(r_q->hdr_name), ps, depth);
+       smb_io_unistr2("", &(r_q->uni_name), r_q->hdr_name.buffer, ps, depth);
+
+       prs_align(ps);
+       
+       prs_uint32("unknown_0", ps, depth, &(r_q->unknown_0));
+       prs_uint32("unknown_1", ps, depth, &(r_q->unknown_1));
+}
+
+
+/*******************************************************************
+creates a structure.
+********************************************************************/
+void make_reg_r_open_entry(REG_R_OPEN_ENTRY *r_r,
+                               POLICY_HND *pol, uint32 status)
+{
+       if (r_r == NULL) return;
+
+       memcpy(&(r_r->pol), pol, sizeof(r_r->pol));
+       r_r->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void reg_io_r_open_entry(char *desc,  REG_R_OPEN_ENTRY *r_r, prs_struct *ps, int depth)
+{
+       if (r_r == NULL) return;
+
+       prs_debug(ps, depth, desc, "reg_io_r_open_entry");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_pol_hnd("", &(r_r->pol), ps, depth);
+
+       prs_uint32("status", ps, depth, &(r_r->status));
+}
+
index 3e734d7edb11930834ffb92558f98a2b36e3bca3..17716a274854f913b4963acf0074db7208c565f7 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* removed in SAMBA_2_0 branch. */
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+
+/*******************************************************************
+makes a SAMR_Q_CLOSE_HND structure.
+********************************************************************/
+void make_samr_q_close_hnd(SAMR_Q_CLOSE_HND *q_c, POLICY_HND *hnd)
+{
+       if (q_c == NULL || hnd == NULL) return;
+
+       DEBUG(5,("make_samr_q_close_hnd\n"));
+
+       memcpy(&(q_c->pol), hnd, sizeof(q_c->pol));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_close_hnd(char *desc,  SAMR_Q_CLOSE_HND *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_close_hnd");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_close_hnd(char *desc,  SAMR_R_CLOSE_HND *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_close_hnd");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_samr_q_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
+                               POLICY_HND *connect_pol, uint32 rid,
+                               DOM_SID *sid)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("samr_make_q_open_domain\n"));
+
+       memcpy(&q_u->connect_pol, connect_pol, sizeof(q_u->connect_pol));
+       q_u->rid = rid;
+       make_dom_sid2(&(q_u->dom_sid), sid);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_open_domain(char *desc,  SAMR_Q_OPEN_DOMAIN *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_open_domain");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("connect_pol", &(q_u->connect_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("rid", ps, depth, &(q_u->rid));
+
+       smb_io_dom_sid2("sid", &(q_u->dom_sid), ps, depth); 
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_open_domain(char *desc,  SAMR_R_OPEN_DOMAIN *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_open_domain");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("domain_pol", &(r_u->domain_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_samr_q_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u, POLICY_HND *user_pol)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("samr_make_q_unknown_2c\n"));
+
+       memcpy(&q_u->user_pol, user_pol, sizeof(q_u->user_pol));
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_unknown_2c(char *desc,  SAMR_Q_UNKNOWN_2C *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_unknown_2c");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("user_pol", &(q_u->user_pol), ps, depth); 
+       prs_align(ps);
+}
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_samr_r_unknown_2c(SAMR_R_UNKNOWN_2C *q_u, uint32 status)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("samr_make_r_unknown_2c\n"));
+
+       q_u->unknown_0 = 0x00160000;
+       q_u->unknown_1 = 0x00000000;
+       q_u->status    = status;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_unknown_2c(char *desc,  SAMR_R_UNKNOWN_2C *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_unknown_2c");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("unknown_0", ps, depth, &(r_u->unknown_0));
+       prs_uint32("unknown_1", ps, depth, &(r_u->unknown_1));
+       prs_uint32("status   ", ps, depth, &(r_u->status   ));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_samr_q_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
+                               POLICY_HND *user_pol, uint16 switch_value)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("samr_make_q_unknown_3\n"));
+
+       memcpy(&q_u->user_pol, user_pol, sizeof(q_u->user_pol));
+       q_u->switch_value = switch_value;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_unknown_3(char *desc,  SAMR_Q_UNKNOWN_3 *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_unknown_3");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("user_pol", &(q_u->user_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint16("switch_value", ps, depth, &(q_u->switch_value));
+       prs_align(ps);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_samr_q_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
+                               POLICY_HND *domain_pol, uint16 switch_value)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("samr_make_q_query_dom_info\n"));
+
+       memcpy(&q_u->domain_pol, domain_pol, sizeof(q_u->domain_pol));
+       q_u->switch_value = switch_value;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_query_dom_info(char *desc,  SAMR_Q_QUERY_DOMAIN_INFO *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_query_dom_info");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("domain_pol", &(q_u->domain_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint16("switch_value", ps, depth, &(q_u->switch_value));
+       prs_align(ps);
+}
+
+/*******************************************************************
+makes a structure.
+********************************************************************/
+void make_unk_info2(SAM_UNK_INFO_2 *u_2, char *domain, char *server)
+{
+       int len_domain = strlen(domain);
+       int len_server = strlen(server);
+
+       if (u_2 == NULL) return;
+
+       u_2->unknown_0 = 0x00000000;
+       u_2->unknown_1 = 0x80000000;
+       u_2->unknown_2 = 0x00000000;
+
+       u_2->ptr_0 = 1;
+       make_uni_hdr(&(u_2->hdr_domain), len_domain, len_domain, 1);
+       make_uni_hdr(&(u_2->hdr_server), len_server, len_server, 1);
+
+       u_2->seq_num = 0x10000000;
+       u_2->unknown_3 = 0x00000000;
+       
+       u_2->unknown_4  = 0x00000001;
+       u_2->unknown_5  = 0x00000003;
+       u_2->unknown_6  = 0x00000001;
+       u_2->num_domain_usrs  = 0x00000008;
+       u_2->num_domain_grps = 0x00000003;
+       u_2->num_local_grps = 0x00000003;
+
+       memset(u_2->padding, 0, sizeof(u_2->padding)); /* 12 bytes zeros */
+
+       make_unistr2(&u_2->uni_domain, domain, len_domain);
+       make_unistr2(&u_2->uni_server, server, len_server);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void sam_io_unk_info2(char *desc, SAM_UNK_INFO_2 *u_2, prs_struct *ps, int depth)
+{
+       if (u_2 == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_unk_info2");
+       depth++;
+
+       prs_uint32("unknown_0", ps, depth, &u_2->unknown_0); /* 0x0000 0000 */
+       prs_uint32("unknown_1", ps, depth, &u_2->unknown_1); /* 0x8000 0000 */
+       prs_uint32("unknown_2", ps, depth, &u_2->unknown_2); /* 0x0000 0000 */
+
+       prs_uint32("ptr_0", ps, depth, &u_2->ptr_0);     /* pointer to unknown structure */
+       smb_io_unihdr("hdr_domain", &u_2->hdr_domain, ps, depth); /* domain name unicode header */
+       smb_io_unihdr("hdr_server", &u_2->hdr_server, ps, depth); /* server name unicode header */
+
+       /* put all the data in here, at the moment, including what the above
+          pointer is referring to
+        */
+
+       prs_uint32("seq_num ", ps, depth, &u_2->seq_num ); /* 0x0000 0099 or 0x1000 0000 */
+       prs_uint32("unknown_3 ", ps, depth, &u_2->unknown_3 ); /* 0x0000 0000 */
+       
+       prs_uint32("unknown_4 ", ps, depth, &u_2->unknown_4 ); /* 0x0000 0001 */
+       prs_uint32("unknown_5 ", ps, depth, &u_2->unknown_5 ); /* 0x0000 0003 */
+       prs_uint32("unknown_6 ", ps, depth, &u_2->unknown_6 ); /* 0x0000 0001 */
+       prs_uint32("num_domain_usrs ", ps, depth, &u_2->num_domain_usrs ); /* 0x0000 0008 */
+       prs_uint32("num_domain_grps", ps, depth, &u_2->num_domain_grps); /* 0x0000 0003 */
+       prs_uint32("num_local_grps", ps, depth, &u_2->num_local_grps); /* 0x0000 0003 */
+
+       prs_uint8s(False, "padding", ps, depth, u_2->padding, sizeof(u_2->padding)); /* 12 bytes zeros */
+
+       smb_io_unistr2( "uni_domain", &u_2->uni_domain, u_2->hdr_domain.buffer, ps, depth); /* domain name unicode string */
+       smb_io_unistr2( "uni_server", &u_2->uni_server, u_2->hdr_server.buffer, ps, depth); /* server name unicode string */
+
+       prs_align(ps);
+
+}
+
+/*******************************************************************
+makes a SAMR_R_QUERY_DOMAIN_INFO structure.
+********************************************************************/
+void make_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO *r_u, 
+                               uint16 switch_value, SAM_UNK_CTR *ctr,
+                               uint32 status)
+{
+       if (r_u == NULL || ctr == NULL) return;
+
+       DEBUG(5,("make_samr_r_query_dom_info\n"));
+
+       r_u->ptr_0 = 0;
+       r_u->switch_value = 0;
+       r_u->status = status; /* return status */
+
+       if (status == 0)
+       {
+               r_u->switch_value = switch_value;
+               r_u->ptr_0 = 1;
+               r_u->ctr = ctr;
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_query_dom_info(char *desc, SAMR_R_QUERY_DOMAIN_INFO *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_query_dom_info");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_0       ", ps, depth, &(r_u->ptr_0));
+       prs_uint16("switch_value", ps, depth, &(r_u->switch_value));
+       prs_align(ps);
+
+       if (r_u->ptr_0 != 0 && r_u->ctr != NULL)
+       {
+               switch (r_u->switch_value)
+               {
+                       case 0x02:
+                       {
+                               sam_io_unk_info2("unk_inf2", &r_u->ctr->info.inf2, ps, depth);
+                               break;
+                       }
+                       default:
+                       {
+                               DEBUG(3,("samr_io_r_query_dom_info: unknown switch level 0x%x\n",
+                                         r_u->switch_value));
+                               return;
+                       }
+               }
+       }
+}
+
+
+/*******************************************************************
+ makes a DOM_SID3 structure.
+
+ calculate length by adding up the size of the components.
+ ********************************************************************/
+void make_dom_sid3(DOM_SID3 *sid3, uint16 unk_0, uint16 unk_1, DOM_SID *sid)
+{
+       if (sid3 == NULL) return;
+
+    sid3->sid = *sid;
+       sid3->len = 2 + 8 + sid3->sid.num_auths * 4;
+}
+
+/*******************************************************************
+reads or writes a SAM_SID3 structure.
+
+this one's odd, because the length (in bytes) is specified at the beginning.
+the length _includes_ the length of the length, too :-)
+
+********************************************************************/
+static void sam_io_dom_sid3(char *desc,  DOM_SID3 *sid3, prs_struct *ps, int depth)
+{
+       if (sid3 == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_dom_sid3");
+       depth++;
+
+       prs_uint16("len", ps, depth, &(sid3->len));
+       prs_align(ps);
+       smb_io_dom_sid("", &(sid3->sid), ps, depth); 
+}
+
+/*******************************************************************
+makes a SAMR_R_UNKNOWN3 structure.
+
+unknown_2   : 0x0001
+unknown_3   : 0x8004
+
+unknown_4,5 : 0x0000 0014
+
+unknown_6   : 0x0002
+unknown_7   : 0x5800 or 0x0070
+
+********************************************************************/
+static void make_sam_sid_stuff(SAM_SID_STUFF *stf,
+                               uint16 unknown_2, uint16 unknown_3,
+                               uint32 unknown_4, uint16 unknown_6, uint16 unknown_7,
+                               int num_sid3s, DOM_SID3 sid3[MAX_SAM_SIDS])
+{
+       stf->unknown_2 = unknown_2;
+       stf->unknown_3 = unknown_3;
+
+       memset((char *)stf->padding1, '\0', sizeof(stf->padding1));
+
+       stf->unknown_4 = unknown_4;
+       stf->unknown_5 = unknown_4;
+
+       stf->unknown_6 = unknown_6;
+       stf->unknown_7 = unknown_7;
+
+       stf->num_sids  = num_sid3s;
+
+       stf->padding2  = 0x0000;
+
+       memcpy(stf->sid, sid3, sizeof(DOM_SID3) * num_sid3s);
+}
+
+/*******************************************************************
+reads or writes a SAM_SID_STUFF structure.
+********************************************************************/
+static void sam_io_sid_stuff(char *desc,  SAM_SID_STUFF *stf, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (stf == NULL) return;
+
+       DEBUG(5,("make_sam_sid_stuff\n"));
+
+       prs_uint16("unknown_2", ps, depth, &(stf->unknown_2));
+       prs_uint16("unknown_3", ps, depth, &(stf->unknown_3));
+
+       prs_uint8s(False, "padding1", ps, depth, stf->padding1, sizeof(stf->padding1)); 
+       
+       prs_uint32("unknown_4", ps, depth, &(stf->unknown_4));
+       prs_uint32("unknown_5", ps, depth, &(stf->unknown_5));
+       prs_uint16("unknown_6", ps, depth, &(stf->unknown_6));
+       prs_uint16("unknown_7", ps, depth, &(stf->unknown_7));
+
+       prs_uint32("num_sids ", ps, depth, &(stf->num_sids ));
+       prs_uint16("padding2 ", ps, depth, &(stf->padding2 ));
+
+       SMB_ASSERT_ARRAY(stf->sid, stf->num_sids);
+
+       for (i = 0; i < stf->num_sids; i++)
+       {
+               sam_io_dom_sid3("", &(stf->sid[i]), ps, depth); 
+       }
+}
+
+/*******************************************************************
+reads or writes a SAMR_R_UNKNOWN3 structure.
+********************************************************************/
+void make_samr_r_unknown_3(SAMR_R_UNKNOWN_3 *r_u,
+                               uint16 unknown_2, uint16 unknown_3,
+                               uint32 unknown_4, uint16 unknown_6, uint16 unknown_7,
+                               int num_sid3s, DOM_SID3 sid3[MAX_SAM_SIDS],
+                               uint32 status)
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("samr_make_r_unknown_3\n"));
+
+       r_u->ptr_0 = 0;
+       r_u->ptr_1 = 0;
+
+       if (status == 0x0)
+       {
+               r_u->ptr_0 = 1;
+               r_u->ptr_1 = 1;
+               make_sam_sid_stuff(&(r_u->sid_stuff), unknown_2, unknown_3,
+                      unknown_4, unknown_6, unknown_7,
+                      num_sid3s, sid3);
+       }
+
+       r_u->status = status;
+}
+
+
+/*******************************************************************
+reads or writes a SAMR_R_UNKNOWN_3 structure.
+
+this one's odd, because the daft buggers use a different mechanism
+for writing out the array of sids. they put the number of sids in
+only one place: they've calculated the length of each sid and jumped
+by that amount.  then, retrospectively, the length of the whole buffer
+is put at the beginning of the data stream.
+
+wierd.  
+
+********************************************************************/
+void samr_io_r_unknown_3(char *desc,  SAMR_R_UNKNOWN_3 *r_u, prs_struct *ps, int depth)
+{
+       int ptr_len0=0;
+       int ptr_len1=0;
+       int ptr_sid_stuff = 0;
+
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_unknown_3");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_0         ", ps, depth, &(r_u->ptr_0         ));
+
+       if (ps->io) 
+       {
+               /* reading.  do the length later */
+               prs_uint32("sid_stuff_len0", ps, depth, &(r_u->sid_stuff_len0));
+       }
+       else
+       {
+               /* storing */
+               ptr_len0 = ps->offset; ps->offset += 4;
+       }
+
+       if (r_u->ptr_0 != 0)
+       {
+               prs_uint32("ptr_1         ", ps, depth, &(r_u->ptr_1         ));
+               if (ps->io)
+               {
+                       /* reading.  do the length later */
+                       prs_uint32("sid_stuff_len1", ps, depth, &(r_u->sid_stuff_len1));
+               }
+               else
+               {
+                       /* storing */
+                       ptr_len1 = ps->offset; ps->offset += 4;
+               }
+
+               if (r_u->ptr_1 != 0)
+               {
+                       ptr_sid_stuff = ps->offset;
+                       sam_io_sid_stuff("", &(r_u->sid_stuff), ps, depth); 
+               }
+       }
+
+       if (!(ps->io)) /* storing not reading.  do the length, now. */
+       {
+               if (ptr_sid_stuff != 0)
+               {
+                       uint32 sid_stuff_len = ps->offset - ptr_sid_stuff;
+                       int old_len = ps->offset;
+
+                       ps->offset = ptr_len0;
+                       prs_uint32("sid_stuff_len0", ps, depth, &sid_stuff_len); 
+
+                       ps->offset = ptr_len1;
+                       prs_uint32("sid_stuff_len1", ps, depth, &sid_stuff_len);
+
+                       ps->offset = old_len;
+               }
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+reads or writes a SAM_STR1 structure.
+********************************************************************/
+static void sam_io_sam_str1(char *desc,  SAM_STR1 *sam, uint32 acct_buf, uint32 name_buf, uint32 desc_buf, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_str1");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_unistr2("unistr2", &(sam->uni_acct_name), acct_buf, ps, depth); /* account name unicode string */
+       smb_io_unistr2("unistr2", &(sam->uni_full_name), name_buf, ps, depth); /* full name unicode string */
+       smb_io_unistr2("unistr2", &(sam->uni_acct_desc), desc_buf, ps, depth); /* account description unicode string */
+}
+
+/*******************************************************************
+makes a SAM_ENTRY1 structure.
+********************************************************************/
+static void make_sam_entry1(SAM_ENTRY1 *sam, uint32 user_idx, 
+                               uint32 len_sam_name, uint32 len_sam_full, uint32 len_sam_desc,
+                               uint32 rid_user, uint16 acb_info)
+{
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_entry1\n"));
+
+       sam->user_idx = user_idx;
+       sam->rid_user = rid_user;
+       sam->acb_info = acb_info;
+       sam->pad      = 0;
+
+       make_uni_hdr(&(sam->hdr_acct_name), len_sam_name, len_sam_name, len_sam_name != 0);
+       make_uni_hdr(&(sam->hdr_user_name), len_sam_full, len_sam_full, len_sam_full != 0);
+       make_uni_hdr(&(sam->hdr_user_desc), len_sam_desc, len_sam_desc, len_sam_desc != 0);
+}
+
+/*******************************************************************
+reads or writes a SAM_ENTRY1 structure.
+********************************************************************/
+static void sam_io_sam_entry1(char *desc,  SAM_ENTRY1 *sam, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_entry1");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("user_idx ", ps, depth, &(sam->user_idx ));
+
+       prs_uint32("rid_user ", ps, depth, &(sam->rid_user ));
+       prs_uint16("acb_info ", ps, depth, &(sam->acb_info ));
+       prs_uint16("pad      ", ps, depth, &(sam->pad      ));
+
+       smb_io_unihdr("unihdr", &(sam->hdr_acct_name), ps, depth); /* account name unicode string header */
+       smb_io_unihdr("unihdr", &(sam->hdr_user_name), ps, depth); /* account name unicode string header */
+       smb_io_unihdr("unihdr", &(sam->hdr_user_desc), ps, depth); /* account name unicode string header */
+}
+
+/*******************************************************************
+reads or writes a SAM_STR2 structure.
+********************************************************************/
+static void sam_io_sam_str2(char *desc,  SAM_STR2 *sam, uint32 acct_buf, uint32 desc_buf, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_str2");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_unistr2("unistr2", &(sam->uni_srv_name), acct_buf, ps, depth); /* account name unicode string */
+       smb_io_unistr2("unistr2", &(sam->uni_srv_desc), desc_buf, ps, depth); /* account description unicode string */
+}
+
+/*******************************************************************
+makes a SAM_ENTRY2 structure.
+********************************************************************/
+static void make_sam_entry2(SAM_ENTRY2 *sam, uint32 user_idx, 
+                               uint32 len_sam_name, uint32 len_sam_desc,
+                               uint32 rid_user, uint16 acb_info)
+{
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_entry2\n"));
+
+       sam->user_idx = user_idx;
+       sam->rid_user = rid_user;
+       sam->acb_info = acb_info;
+       sam->pad      = 0;
+
+       make_uni_hdr(&(sam->hdr_srv_name), len_sam_name, len_sam_name, len_sam_name != 0);
+       make_uni_hdr(&(sam->hdr_srv_desc), len_sam_desc, len_sam_desc, len_sam_desc != 0);
+}
+
+/*******************************************************************
+reads or writes a SAM_ENTRY2 structure.
+********************************************************************/
+static void sam_io_sam_entry2(char *desc,  SAM_ENTRY2 *sam, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_entry2");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("user_idx ", ps, depth, &(sam->user_idx ));
+
+       prs_uint32("rid_user ", ps, depth, &(sam->rid_user ));
+       prs_uint16("acb_info ", ps, depth, &(sam->acb_info ));
+       prs_uint16("pad      ", ps, depth, &(sam->pad      ));
+
+       smb_io_unihdr("unihdr", &(sam->hdr_srv_name), ps, depth); /* account name unicode string header */
+       smb_io_unihdr("unihdr", &(sam->hdr_srv_desc), ps, depth); /* account name unicode string header */
+}
+
+/*******************************************************************
+reads or writes a SAM_STR3 structure.
+********************************************************************/
+static void sam_io_sam_str3(char *desc,  SAM_STR3 *sam, uint32 acct_buf, uint32 desc_buf, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_str3");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_unistr2("unistr2", &(sam->uni_grp_name), acct_buf, ps, depth); /* account name unicode string */
+       smb_io_unistr2("unistr2", &(sam->uni_grp_desc), desc_buf, ps, depth); /* account description unicode string */
+}
+
+/*******************************************************************
+makes a SAM_ENTRY3 structure.
+********************************************************************/
+static void make_sam_entry3(SAM_ENTRY3 *sam, uint32 grp_idx, 
+                               uint32 len_grp_name, uint32 len_grp_desc, uint32 rid_grp)
+{
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_entry3\n"));
+
+       sam->grp_idx = grp_idx;
+       sam->rid_grp = rid_grp;
+       sam->attr    = 0x07; /* group rid attributes - gets ignored by nt 4.0 */
+
+       make_uni_hdr(&(sam->hdr_grp_name), len_grp_name, len_grp_name, len_grp_name != 0);
+       make_uni_hdr(&(sam->hdr_grp_desc), len_grp_desc, len_grp_desc, len_grp_desc != 0);
+}
+
+/*******************************************************************
+reads or writes a SAM_ENTRY3 structure.
+********************************************************************/
+static void sam_io_sam_entry3(char *desc,  SAM_ENTRY3 *sam, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_entry3");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("grp_idx", ps, depth, &(sam->grp_idx));
+
+       prs_uint32("rid_grp", ps, depth, &(sam->rid_grp));
+       prs_uint32("attr   ", ps, depth, &(sam->attr   ));
+
+       smb_io_unihdr("unihdr", &(sam->hdr_grp_name), ps, depth); /* account name unicode string header */
+       smb_io_unihdr("unihdr", &(sam->hdr_grp_desc), ps, depth); /* account name unicode string header */
+}
+
+/*******************************************************************
+makes a SAM_ENTRY structure.
+********************************************************************/
+static void make_sam_entry(SAM_ENTRY *sam, uint32 len_sam_name, uint32 rid)
+{
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_entry\n"));
+
+       sam->rid = rid;
+       make_uni_hdr(&(sam->hdr_name), len_sam_name, len_sam_name, len_sam_name != 0);
+}
+
+/*******************************************************************
+reads or writes a SAM_ENTRY structure.
+********************************************************************/
+static void sam_io_sam_entry(char *desc,  SAM_ENTRY *sam, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_entry");
+       depth++;
+
+       prs_align(ps);
+       prs_uint32("rid", ps, depth, &(sam->rid ));
+       smb_io_unihdr("unihdr", &(sam->hdr_name), ps, depth); /* account name unicode string header */
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_ENUM_DOM_USERS structure.
+********************************************************************/
+void make_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_e, POLICY_HND *pol,
+                               uint16 req_num_entries, uint16 unk_0,
+                               uint16 acb_mask, uint16 unk_1, uint32 size)
+{
+       if (q_e == NULL || pol == NULL) return;
+
+       DEBUG(5,("make_q_enum_dom_users\n"));
+
+       memcpy(&(q_e->pol), pol, sizeof(*pol));
+
+       q_e->req_num_entries = req_num_entries; /* zero indicates lots */
+       q_e->unknown_0 = unk_0; /* this gets returned in the response */
+       q_e->acb_mask  = acb_mask;
+       q_e->unknown_1 = unk_1;
+       q_e->max_size = size;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_enum_dom_users(char *desc,  SAMR_Q_ENUM_DOM_USERS *q_e, prs_struct *ps, int depth)
+{
+       if (q_e == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_enum_dom_users");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint16("req_num_entries", ps, depth, &(q_e->req_num_entries));
+       prs_uint16("unknown_0      ", ps, depth, &(q_e->unknown_0      ));
+
+       prs_uint16("acb_mask       ", ps, depth, &(q_e->acb_mask       ));
+       prs_uint16("unknown_1      ", ps, depth, &(q_e->unknown_1      ));
+
+       prs_uint32("max_size       ", ps, depth, &(q_e->max_size       ));
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+makes a SAMR_R_ENUM_DOM_USERS structure.
+********************************************************************/
+void make_samr_r_enum_dom_users(SAMR_R_ENUM_DOM_USERS *r_u,
+               uint16 total_num_entries, uint16 unk_0,
+               uint32 num_sam_entries, SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], uint32 status)
+{
+       int i;
+
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_enum_dom_users\n"));
+
+       if (num_sam_entries >= MAX_SAM_ENTRIES)
+       {
+               num_sam_entries = MAX_SAM_ENTRIES;
+               DEBUG(5,("limiting number of entries to %d\n",
+                        num_sam_entries));
+       }
+
+       r_u->total_num_entries = total_num_entries;
+       r_u->unknown_0         = unk_0;
+
+       if (total_num_entries > 0)
+       {
+               r_u->ptr_entries1 = 1;
+               r_u->ptr_entries2 = 1;
+               r_u->num_entries2 = num_sam_entries;
+               r_u->num_entries3 = num_sam_entries;
+
+               SMB_ASSERT_ARRAY(r_u->sam, num_sam_entries);
+               SMB_ASSERT_ARRAY(r_u->uni_acct_name, num_sam_entries);
+
+               for (i = 0; i < num_sam_entries; i++)
+               {
+                       make_sam_entry(&(r_u->sam[i]),
+                                      pass[i].uni_user_name.uni_str_len,
+                                      pass[i].user_rid);
+
+                       copy_unistr2(&(r_u->uni_acct_name[i]), &(pass[i].uni_user_name));
+               }
+
+               r_u->num_entries4 = num_sam_entries;
+       }
+       else
+       {
+               r_u->ptr_entries1 = 0;
+               r_u->num_entries2 = num_sam_entries;
+               r_u->ptr_entries2 = 1;
+       }
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_enum_dom_users(char *desc,  SAMR_R_ENUM_DOM_USERS *r_u, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_enum_dom_users");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint16("total_num_entries", ps, depth, &(r_u->total_num_entries));
+       prs_uint16("unknown_0        ", ps, depth, &(r_u->unknown_0        ));
+       prs_uint32("ptr_entries1", ps, depth, &(r_u->ptr_entries1));
+
+       if (r_u->total_num_entries != 0 && r_u->ptr_entries1 != 0)
+       {
+               prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+               prs_uint32("ptr_entries2", ps, depth, &(r_u->ptr_entries2));
+               prs_uint32("num_entries3", ps, depth, &(r_u->num_entries3));
+
+               SMB_ASSERT_ARRAY(r_u->sam, r_u->num_entries2);
+
+               for (i = 0; i < r_u->num_entries2; i++)
+               {
+                       prs_grow(ps);
+                       sam_io_sam_entry("", &(r_u->sam[i]), ps, depth);
+               }
+
+               SMB_ASSERT_ARRAY(r_u->uni_acct_name, r_u->num_entries2);
+
+               for (i = 0; i < r_u->num_entries2; i++)
+               {
+                       prs_grow(ps);
+                       smb_io_unistr2("", &(r_u->uni_acct_name[i]), r_u->sam[i].hdr_name.buffer, ps, depth);
+               }
+
+               prs_align(ps);
+
+               prs_uint32("num_entries4", ps, depth, &(r_u->num_entries4));
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+makes a SAMR_Q_ENUM_DOM_ALIASES structure.
+********************************************************************/
+void make_samr_q_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_e, POLICY_HND *pol, uint32 size)
+{
+       if (q_e == NULL || pol == NULL) return;
+
+       DEBUG(5,("make_q_enum_dom_aliases\n"));
+
+       memcpy(&(q_e->pol), pol, sizeof(*pol));
+
+       q_e->unknown_0 = 0;
+       q_e->max_size = size;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_enum_dom_aliases(char *desc,  SAMR_Q_ENUM_DOM_ALIASES *q_e, prs_struct *ps, int depth)
+{
+       if (q_e == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_enum_dom_aliases");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("unknown_0", ps, depth, &(q_e->unknown_0));
+       prs_uint32("max_size ", ps, depth, &(q_e->max_size ));
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+makes a SAMR_R_ENUM_DOM_ALIASES structure.
+********************************************************************/
+void make_samr_r_enum_dom_aliases(SAMR_R_ENUM_DOM_ALIASES *r_u,
+               uint32 num_sam_entries, SAM_USER_INFO_21 grps[MAX_SAM_ENTRIES],
+               uint32 status)
+{
+       int i;
+
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_enum_dom_aliases\n"));
+
+       if (num_sam_entries >= MAX_SAM_ENTRIES)
+       {
+               num_sam_entries = MAX_SAM_ENTRIES;
+               DEBUG(5,("limiting number of entries to %d\n", 
+                        num_sam_entries));
+       }
+
+       r_u->num_entries  = num_sam_entries;
+
+       if (num_sam_entries > 0)
+       {
+               r_u->ptr_entries  = 1;
+               r_u->num_entries2 = num_sam_entries;
+               r_u->ptr_entries2 = 1;
+               r_u->num_entries3 = num_sam_entries;
+
+               SMB_ASSERT_ARRAY(r_u->sam, num_sam_entries);
+
+               for (i = 0; i < num_sam_entries; i++)
+               {
+                       make_sam_entry(&(r_u->sam[i]),
+                                      grps[i].uni_user_name.uni_str_len,
+                                      grps[i].user_rid);
+
+                       copy_unistr2(&(r_u->uni_grp_name[i]), &(grps[i].uni_user_name));
+               }
+
+               r_u->num_entries4 = num_sam_entries;
+       }
+       else
+       {
+               r_u->ptr_entries = 0;
+       }
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_enum_dom_aliases(char *desc,  SAMR_R_ENUM_DOM_ALIASES *r_u, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_enum_dom_aliases");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries", ps, depth, &(r_u->num_entries));
+       prs_uint32("ptr_entries", ps, depth, &(r_u->ptr_entries));
+
+       if (r_u->num_entries != 0 && r_u->ptr_entries != 0)
+       {
+               prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+               prs_uint32("ptr_entries2", ps, depth, &(r_u->ptr_entries2));
+               prs_uint32("num_entries3", ps, depth, &(r_u->num_entries3));
+
+               SMB_ASSERT_ARRAY(r_u->sam, r_u->num_entries);
+
+               for (i = 0; i < r_u->num_entries; i++)
+               {
+                       sam_io_sam_entry("", &(r_u->sam[i]), ps, depth);
+               }
+
+               for (i = 0; i < r_u->num_entries; i++)
+               {
+                       smb_io_unistr2("", &(r_u->uni_grp_name[i]), r_u->sam[i].hdr_name.buffer, ps, depth);
+               }
+
+               prs_align(ps);
+
+               prs_uint32("num_entries4", ps, depth, &(r_u->num_entries4));
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_QUERY_DISPINFO structure.
+********************************************************************/
+void make_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_e, POLICY_HND *pol,
+                               uint16 switch_level, uint32 start_idx, uint32 size)
+{
+       if (q_e == NULL || pol == NULL) return;
+
+       DEBUG(5,("make_q_query_dispinfo\n"));
+
+       memcpy(&(q_e->pol), pol, sizeof(*pol));
+
+       q_e->switch_level = switch_level;
+
+       q_e->unknown_0 = 0;
+       q_e->start_idx = start_idx;
+       q_e->unknown_1 = 0x000007d0;
+       q_e->max_size  = size;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_query_dispinfo(char *desc,  SAMR_Q_QUERY_DISPINFO *q_e, prs_struct *ps, int depth)
+{
+       if (q_e == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_query_dispinfo");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint16("switch_level", ps, depth, &(q_e->switch_level));
+       prs_uint16("unknown_0   ", ps, depth, &(q_e->unknown_0   ));
+       prs_uint32("start_idx   ", ps, depth, &(q_e->start_idx   ));
+       prs_uint32("unknown_1   ", ps, depth, &(q_e->unknown_1   ));
+       prs_uint32("max_size    ", ps, depth, &(q_e->max_size    ));
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+makes a SAM_INFO_2 structure.
+********************************************************************/
+void make_sam_info_2(SAM_INFO_2 *sam, uint32 acb_mask,
+               uint32 start_idx, uint32 num_sam_entries,
+               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES])
+{
+       int i;
+       int entries_added;
+
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_info_2\n"));
+
+       if (num_sam_entries >= MAX_SAM_ENTRIES)
+       {
+               num_sam_entries = MAX_SAM_ENTRIES;
+               DEBUG(5,("limiting number of entries to %d\n", 
+                        num_sam_entries));
+       }
+
+       for (i = start_idx, entries_added = 0; i < num_sam_entries; i++)
+       {
+               if (IS_BITS_SET_ALL(pass[i].acb_info, acb_mask))
+               {
+                       make_sam_entry2(&(sam->sam[entries_added]),
+                                       start_idx + entries_added + 1,
+                                       pass[i].uni_user_name.uni_str_len,
+                                       pass[i].uni_acct_desc.uni_str_len,
+                                       pass[i].user_rid,
+                                       pass[i].acb_info);
+
+                       copy_unistr2(&(sam->str[entries_added].uni_srv_name), &(pass[i].uni_user_name));
+                       copy_unistr2(&(sam->str[entries_added].uni_srv_desc), &(pass[i].uni_acct_desc));
+
+                       entries_added++;
+               }
+
+               sam->num_entries   = entries_added;
+               sam->ptr_entries   = 1;
+               sam->num_entries2  = entries_added;
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void sam_io_sam_info_2(char *desc,  SAM_INFO_2 *sam, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_info_2");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries  ", ps, depth, &(sam->num_entries  ));
+       prs_uint32("ptr_entries  ", ps, depth, &(sam->ptr_entries  ));
+
+       prs_uint32("num_entries2 ", ps, depth, &(sam->num_entries2 ));
+
+       SMB_ASSERT_ARRAY(sam->sam, sam->num_entries);
+
+       for (i = 0; i < sam->num_entries; i++)
+       {
+               prs_grow(ps);
+               sam_io_sam_entry2("", &(sam->sam[i]), ps, depth);
+       }
+
+       for (i = 0; i < sam->num_entries; i++)
+       {
+               prs_grow(ps);
+               sam_io_sam_str2 ("", &(sam->str[i]),
+                                                        sam->sam[i].hdr_srv_name.buffer,
+                                                        sam->sam[i].hdr_srv_desc.buffer,
+                                                        ps, depth);
+       }
+}
+
+
+/*******************************************************************
+makes a SAM_INFO_1 structure.
+********************************************************************/
+void make_sam_info_1(SAM_INFO_1 *sam, uint32 acb_mask,
+               uint32 start_idx, uint32 num_sam_entries,
+               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES])
+{
+       int i;
+       int entries_added;
+
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_info_1\n"));
+
+       if (num_sam_entries >= MAX_SAM_ENTRIES)
+       {
+               num_sam_entries = MAX_SAM_ENTRIES;
+               DEBUG(5,("limiting number of entries to %d\n", 
+                        num_sam_entries));
+       }
+
+       for (i = start_idx, entries_added = 0; i < num_sam_entries; i++)
+       {
+               if (IS_BITS_SET_ALL(pass[i].acb_info, acb_mask))
+               {
+                       make_sam_entry1(&(sam->sam[entries_added]),
+                                               start_idx + entries_added + 1,
+                                               pass[i].uni_user_name.uni_str_len,
+                                               pass[i].uni_full_name.uni_str_len, 
+                                               pass[i].uni_acct_desc.uni_str_len,
+                                               pass[i].user_rid,
+                                               pass[i].acb_info);
+
+                       copy_unistr2(&(sam->str[entries_added].uni_acct_name), &(pass[i].uni_user_name));
+                       copy_unistr2(&(sam->str[entries_added].uni_full_name), &(pass[i].uni_full_name));
+                       copy_unistr2(&(sam->str[entries_added].uni_acct_desc), &(pass[i].uni_acct_desc));
+
+                       entries_added++;
+               }
+       }
+
+       sam->num_entries   = entries_added;
+       sam->ptr_entries   = 1;
+       sam->num_entries2  = entries_added;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void sam_io_sam_info_1(char *desc,  SAM_INFO_1 *sam, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_info_1");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries  ", ps, depth, &(sam->num_entries  ));
+       prs_uint32("ptr_entries  ", ps, depth, &(sam->ptr_entries  ));
+
+       prs_uint32("num_entries2 ", ps, depth, &(sam->num_entries2 ));
+
+       SMB_ASSERT_ARRAY(sam->sam, sam->num_entries);
+
+       for (i = 0; i < sam->num_entries; i++)
+       {
+               prs_grow(ps);
+               sam_io_sam_entry1("", &(sam->sam[i]), ps, depth);
+       }
+
+       for (i = 0; i < sam->num_entries; i++)
+       {
+               prs_grow(ps);
+               sam_io_sam_str1 ("", &(sam->str[i]),
+                                                        sam->sam[i].hdr_acct_name.buffer,
+                                                        sam->sam[i].hdr_user_name.buffer,
+                                                        sam->sam[i].hdr_user_desc.buffer,
+                                                        ps, depth);
+       }
+}
+
+
+/*******************************************************************
+makes a SAMR_R_QUERY_DISPINFO structure.
+********************************************************************/
+void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u,
+               uint16 switch_level, SAM_INFO_CTR *ctr, uint32 status)
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_query_dispinfo\n"));
+
+       if (status == 0x0)
+       {
+               r_u->unknown_0 = 0x0000001;
+               r_u->unknown_1 = 0x0000001;
+       }
+       else
+       {
+               r_u->unknown_0 = 0x0;
+               r_u->unknown_1 = 0x0;
+       }
+
+       r_u->switch_level = switch_level;
+       r_u->ctr = ctr;
+       r_u->status = status;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_query_dispinfo(char *desc,  SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_query_dispinfo");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("unknown_0    ", ps, depth, &(r_u->unknown_0    ));
+       prs_uint32("unknown_1    ", ps, depth, &(r_u->unknown_1    ));
+       prs_uint16("switch_level ", ps, depth, &(r_u->switch_level ));
+
+       prs_align(ps);
+
+       switch (r_u->switch_level)
+       {
+               case 0x1:
+               {
+                       sam_io_sam_info_1("users", r_u->ctr->sam.info1, ps, depth);
+                       break;
+               }
+               case 0x2:
+               {
+                       sam_io_sam_info_2("servers", r_u->ctr->sam.info2, ps, depth);
+                       break;
+               }
+               default:
+               {
+                       DEBUG(5,("samr_io_r_query_dispinfo: unknown switch value\n"));
+                       break;
+               }
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_ENUM_DOM_GROUPS structure.
+********************************************************************/
+void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol,
+                               uint16 switch_level, uint32 start_idx, uint32 size)
+{
+       if (q_e == NULL || pol == NULL) return;
+
+       DEBUG(5,("make_q_enum_dom_groups\n"));
+
+       memcpy(&(q_e->pol), pol, sizeof(*pol));
+
+       q_e->switch_level = switch_level;
+
+       q_e->unknown_0 = 0;
+       q_e->start_idx = start_idx;
+       q_e->unknown_1 = 0x000007d0;
+       q_e->max_size  = size;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_enum_dom_groups(char *desc,  SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth)
+{
+       if (q_e == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_enum_dom_groups");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint16("switch_level", ps, depth, &(q_e->switch_level));
+       prs_uint16("unknown_0   ", ps, depth, &(q_e->unknown_0   ));
+       prs_uint32("start_idx   ", ps, depth, &(q_e->start_idx   ));
+       prs_uint32("unknown_1   ", ps, depth, &(q_e->unknown_1   ));
+       prs_uint32("max_size    ", ps, depth, &(q_e->max_size    ));
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+makes a SAMR_R_ENUM_DOM_GROUPS structure.
+********************************************************************/
+void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u,
+               uint32 start_idx, uint32 num_sam_entries,
+               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES],
+               uint32 status)
+{
+       int i;
+       int entries_added;
+
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_enum_dom_groups\n"));
+
+       if (num_sam_entries >= MAX_SAM_ENTRIES)
+       {
+               num_sam_entries = MAX_SAM_ENTRIES;
+               DEBUG(5,("limiting number of entries to %d\n", 
+                        num_sam_entries));
+       }
+
+       if (status == 0x0)
+       {
+               for (i = start_idx, entries_added = 0; i < num_sam_entries; i++)
+               {
+                       make_sam_entry3(&(r_u->sam[entries_added]),
+                                       start_idx + entries_added + 1,
+                                       pass[i].uni_user_name.uni_str_len,
+                                       pass[i].uni_acct_desc.uni_str_len,
+                                       pass[i].user_rid);
+
+                       copy_unistr2(&(r_u->str[entries_added].uni_grp_name), &(pass[i].uni_user_name));
+                       copy_unistr2(&(r_u->str[entries_added].uni_grp_desc), &(pass[i].uni_acct_desc));
+
+                       entries_added++;
+               }
+
+               if (entries_added > 0)
+               {
+                       r_u->unknown_0 = 0x0000492;
+                       r_u->unknown_1 = 0x000049a;
+               }
+               else
+               {
+                       r_u->unknown_0 = 0x0;
+                       r_u->unknown_1 = 0x0;
+               }
+               r_u->switch_level  = 3;
+               r_u->num_entries   = entries_added;
+               r_u->ptr_entries   = 1;
+               r_u->num_entries2  = entries_added;
+       }
+       else
+       {
+               r_u->switch_level = 0;
+       }
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_enum_dom_groups(char *desc,  SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_enum_dom_groups");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("unknown_0    ", ps, depth, &(r_u->unknown_0    ));
+       prs_uint32("unknown_1    ", ps, depth, &(r_u->unknown_1    ));
+       prs_uint32("switch_level ", ps, depth, &(r_u->switch_level ));
+
+       if (r_u->switch_level != 0)
+       {
+               prs_uint32("num_entries  ", ps, depth, &(r_u->num_entries  ));
+               prs_uint32("ptr_entries  ", ps, depth, &(r_u->ptr_entries  ));
+
+               prs_uint32("num_entries2 ", ps, depth, &(r_u->num_entries2 ));
+
+               SMB_ASSERT_ARRAY(r_u->sam, r_u->num_entries);
+
+               for (i = 0; i < r_u->num_entries; i++)
+               {
+                       prs_grow(ps);
+                       sam_io_sam_entry3("", &(r_u->sam[i]), ps, depth);
+               }
+
+               for (i = 0; i < r_u->num_entries; i++)
+               {
+                       prs_grow(ps);
+                       sam_io_sam_str3 ("", &(r_u->str[i]),
+                                            r_u->sam[i].hdr_grp_name.buffer,
+                                            r_u->sam[i].hdr_grp_desc.buffer,
+                                            ps, depth);
+               }
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_QUERY_ALIASINFO structure.
+********************************************************************/
+void make_samr_q_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_e,
+                               POLICY_HND *pol,
+                               uint16 switch_level)
+{
+       if (q_e == NULL || pol == NULL) return;
+
+       DEBUG(5,("make_q_query_aliasinfo\n"));
+
+       memcpy(&(q_e->pol), pol, sizeof(*pol));
+
+       q_e->switch_level = switch_level;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_query_aliasinfo(char *desc,  SAMR_Q_QUERY_ALIASINFO *q_e, prs_struct *ps, int depth)
+{
+       if (q_e == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_query_aliasinfo");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint16("switch_level", ps, depth, &(q_e->switch_level));
+}
+
+
+/*******************************************************************
+makes a SAMR_R_QUERY_ALIASINFO structure.
+********************************************************************/
+void make_samr_r_query_aliasinfo(SAMR_R_QUERY_ALIASINFO *r_u,
+               uint16 switch_value, char *acct_desc,
+               uint32 status)
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_query_aliasinfo\n"));
+
+       r_u->ptr = 0;
+
+       if (status == 0)
+       {
+               r_u->switch_value = switch_value;
+
+               switch (switch_value)
+               {
+                       case 3:
+                       {
+                               int acct_len = acct_desc ? strlen(acct_desc) : 0;
+
+                               r_u->ptr = 1;
+
+                               make_uni_hdr(&(r_u->alias.info3.hdr_acct_desc), acct_len , acct_len, acct_desc ? 1 : 0);
+                               make_unistr2(&(r_u->alias.info3.uni_acct_desc), acct_desc, acct_len);
+
+                               break;
+                       }
+
+                       default:
+                       {
+                               DEBUG(4,("make_samr_r_query_aliasinfo: unsupported switch level\n"));
+                               break;
+                       }
+               }
+       }
+
+       r_u->status = status;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_query_aliasinfo(char *desc,  SAMR_R_QUERY_ALIASINFO *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_query_aliasinfo");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr         ", ps, depth, &(r_u->ptr         ));
+       
+       if (r_u->ptr != 0)
+       {
+               prs_uint16("switch_value", ps, depth, &(r_u->switch_value));
+               prs_align(ps);
+
+               if (r_u->switch_value != 0)
+               {
+                       switch (r_u->switch_value)
+                       {
+                               case 3:
+                               {
+                                       smb_io_unihdr ("", &(r_u->alias.info3.hdr_acct_desc), ps, depth);
+                                       smb_io_unistr2("", &(r_u->alias.info3.uni_acct_desc), r_u->alias.info3.hdr_acct_desc.buffer, ps, depth);
+                                       break;
+                               }
+                               default:
+                               {
+                                       DEBUG(4,("samr_io_r_query_aliasinfo: unsupported switch level\n"));
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+reads or writes a SAMR_Q_LOOKUP_IDS structure.
+********************************************************************/
+void samr_io_q_lookup_ids(char *desc,  SAMR_Q_LOOKUP_IDS *q_u, prs_struct *ps, int depth)
+{
+       fstring tmp;
+       int i;
+
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_lookup_ids");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("num_sids1", ps, depth, &(q_u->num_sids1));
+       prs_uint32("ptr      ", ps, depth, &(q_u->ptr      ));
+       prs_uint32("num_sids2", ps, depth, &(q_u->num_sids2));
+
+       SMB_ASSERT_ARRAY(q_u->ptr_sid, q_u->num_sids2);
+
+       for (i = 0; i < q_u->num_sids2; i++)
+       {
+               slprintf(tmp, sizeof(tmp) - 1, "ptr[%02d]", i);
+               prs_uint32(tmp, ps, depth, &(q_u->ptr_sid[i]));
+       }
+
+       for (i = 0; i < q_u->num_sids2; i++)
+       {
+               if (q_u->ptr_sid[i] != 0)
+               {
+                       prs_grow(ps);
+                       slprintf(tmp, sizeof(tmp)-1, "sid[%02d]", i);
+                       smb_io_dom_sid2(tmp, &(q_u->sid[i]), ps, depth); 
+               }
+       }
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+makes a SAMR_R_LOOKUP_IDS structure.
+********************************************************************/
+void make_samr_r_lookup_ids(SAMR_R_LOOKUP_IDS *r_u,
+               uint32 num_rids, uint32 *rid, uint32 status)
+{
+       int i;
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_lookup_ids\n"));
+
+       if (status == 0x0)
+       {
+               r_u->num_entries  = num_rids;
+               r_u->ptr = 1;
+               r_u->num_entries2 = num_rids;
+
+               SMB_ASSERT_ARRAY(r_u->rid, num_rids);
+
+               for (i = 0; i < num_rids; i++)
+               {
+                       r_u->rid[i] = rid[i];
+               }
+       }
+       else
+       {
+               r_u->num_entries  = 0;
+               r_u->ptr = 0;
+               r_u->num_entries2 = 0;
+       }
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_lookup_ids(char *desc,  SAMR_R_LOOKUP_IDS *r_u, prs_struct *ps, int depth)
+{
+       fstring tmp;
+       int i;
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_lookup_ids");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries", ps, depth, &(r_u->num_entries));
+       prs_uint32("ptr        ", ps, depth, &(r_u->ptr        ));
+       prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+
+       if (r_u->num_entries != 0)
+       {
+               SMB_ASSERT_ARRAY(r_u->rid, r_u->num_entries2);
+
+               for (i = 0; i < r_u->num_entries2; i++)
+               {
+                       slprintf(tmp, sizeof(tmp)-1, "rid[%02d]", i);
+                       prs_uint32(tmp, ps, depth, &(r_u->rid[i]));
+               }
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_lookup_names(char *desc,  SAMR_Q_LOOKUP_NAMES *q_u, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_lookup_names");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("num_rids1", ps, depth, &(q_u->num_rids1));
+       prs_uint32("rid      ", ps, depth, &(q_u->rid      ));
+       prs_uint32("ptr      ", ps, depth, &(q_u->ptr      ));
+       prs_uint32("num_rids2", ps, depth, &(q_u->num_rids2));
+
+       SMB_ASSERT_ARRAY(q_u->hdr_user_name, q_u->num_rids2);
+
+       for (i = 0; i < q_u->num_rids2; i++)
+       {
+               prs_grow(ps);
+               smb_io_unihdr ("", &(q_u->hdr_user_name[i]), ps, depth); 
+       }
+       for (i = 0; i < q_u->num_rids2; i++)
+       {
+               prs_grow(ps);
+               smb_io_unistr2("", &(q_u->uni_user_name[i]), q_u->hdr_user_name[i].buffer, ps, depth); 
+       }
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+makes a SAMR_R_LOOKUP_NAMES structure.
+********************************************************************/
+void make_samr_r_lookup_names(SAMR_R_LOOKUP_NAMES *r_u,
+               uint32 num_rids, uint32 *rid, uint32 status)
+{
+       int i;
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_lookup_names\n"));
+
+       if (status == 0x0)
+       {
+               r_u->num_entries  = num_rids;
+               r_u->undoc_buffer = 1;
+               r_u->num_entries2 = num_rids;
+
+               SMB_ASSERT_ARRAY(r_u->dom_rid, num_rids);
+
+               for (i = 0; i < num_rids; i++)
+               {
+                       make_dom_rid3(&(r_u->dom_rid[i]), rid[i], 0x01);
+               }
+
+               r_u->num_entries3 = num_rids;
+       }
+       else
+       {
+               r_u->num_entries  = 0;
+               r_u->undoc_buffer = 0;
+               r_u->num_entries2 = 0;
+               r_u->num_entries3 = 0;
+       }
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_lookup_names(char *desc,  SAMR_R_LOOKUP_NAMES *r_u, prs_struct *ps, int depth)
+{
+       int i;
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_lookup_names");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries ", ps, depth, &(r_u->num_entries ));
+       prs_uint32("undoc_buffer", ps, depth, &(r_u->undoc_buffer));
+       prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+
+       if (r_u->num_entries != 0)
+       {
+               SMB_ASSERT_ARRAY(r_u->dom_rid, r_u->num_entries2);
+
+               for (i = 0; i < r_u->num_entries2; i++)
+               {
+                       prs_grow(ps);
+                       smb_io_dom_rid3("", &(r_u->dom_rid[i]), ps, depth);
+               }
+
+       }
+
+       prs_uint32("num_entries3", ps, depth, &(r_u->num_entries3));
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_unknown_12(char *desc,  SAMR_Q_UNKNOWN_12 *q_u, prs_struct *ps, int depth)
+{
+       int i;
+       fstring tmp;
+
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_unknown_12");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("num_gids1", ps, depth, &(q_u->num_gids1));
+       prs_uint32("rid      ", ps, depth, &(q_u->rid      ));
+       prs_uint32("ptr      ", ps, depth, &(q_u->ptr      ));
+       prs_uint32("num_gids2", ps, depth, &(q_u->num_gids2));
+
+       SMB_ASSERT_ARRAY(q_u->gid, q_u->num_gids2);
+
+       for (i = 0; i < q_u->num_gids2; i++)
+       {
+               prs_grow(ps);
+               slprintf(tmp, sizeof(tmp) - 1, "gid[%02d]  ", i);
+               prs_uint32(tmp, ps, depth, &(q_u->gid[i]));
+       }
+
+       prs_align(ps);
+}
+
+
+/*******************************************************************
+makes a SAMR_R_UNKNOWN_12 structure.
+********************************************************************/
+void make_samr_r_unknown_12(SAMR_R_UNKNOWN_12 *r_u,
+               uint32 num_aliases, fstring *als_name, uint32 *num_als_usrs,
+               uint32 status)
+{
+       int i;
+       if (r_u == NULL || als_name == NULL || num_als_usrs == NULL) return;
+
+       DEBUG(5,("make_samr_r_unknown_12\n"));
+
+       if (status == 0x0)
+       {
+               r_u->num_aliases1 = num_aliases;
+               r_u->ptr_aliases  = 1;
+               r_u->num_aliases2 = num_aliases;
+
+               r_u->num_als_usrs1 = num_aliases;
+               r_u->ptr_als_usrs  = 1;
+               r_u->num_als_usrs2 = num_aliases;
+
+               SMB_ASSERT_ARRAY(r_u->hdr_als_name, num_aliases);
+
+               for (i = 0; i < num_aliases; i++)
+               {
+                       int als_len = als_name[i] != NULL ? strlen(als_name[i]) : 0;
+                       make_uni_hdr(&(r_u->hdr_als_name[i]), als_len    , als_len, als_name[i] ? 1 : 0);
+                       make_unistr2(&(r_u->uni_als_name[i]), als_name[i], als_len);
+                       r_u->num_als_usrs[i] = num_als_usrs[i];
+               }
+       }
+       else
+       {
+               r_u->num_aliases1 = num_aliases;
+               r_u->ptr_aliases  = 0;
+               r_u->num_aliases2 = num_aliases;
+
+               r_u->num_als_usrs1 = num_aliases;
+               r_u->ptr_als_usrs  = 0;
+               r_u->num_als_usrs2 = num_aliases;
+       }
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_unknown_12(char *desc,  SAMR_R_UNKNOWN_12 *r_u, prs_struct *ps, int depth)
+{
+       int i;
+       fstring tmp;
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_unknown_12");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_aliases1", ps, depth, &(r_u->num_aliases1));
+       prs_uint32("ptr_aliases ", ps, depth, &(r_u->ptr_aliases ));
+       prs_uint32("num_aliases2", ps, depth, &(r_u->num_aliases2));
+
+       if (r_u->ptr_aliases != 0 && r_u->num_aliases1 != 0)
+       {
+               SMB_ASSERT_ARRAY(r_u->hdr_als_name, r_u->num_aliases2);
+
+               for (i = 0; i < r_u->num_aliases2; i++)
+               {
+                       prs_grow(ps);
+                       slprintf(tmp, sizeof(tmp) - 1, "als_hdr[%02d]  ", i);
+                       smb_io_unihdr ("", &(r_u->hdr_als_name[i]), ps, depth); 
+               }
+               for (i = 0; i < r_u->num_aliases2; i++)
+               {
+                       prs_grow(ps);
+                       slprintf(tmp, sizeof(tmp) - 1, "als_str[%02d]  ", i);
+                       smb_io_unistr2("", &(r_u->uni_als_name[i]), r_u->hdr_als_name[i].buffer, ps, depth); 
+               }
+       }
+
+       prs_align(ps);
+
+       prs_uint32("num_als_usrs1", ps, depth, &(r_u->num_als_usrs1));
+       prs_uint32("ptr_als_usrs ", ps, depth, &(r_u->ptr_als_usrs ));
+       prs_uint32("num_als_usrs2", ps, depth, &(r_u->num_als_usrs2));
+
+       if (r_u->ptr_als_usrs != 0 && r_u->num_als_usrs1 != 0)
+       {
+               SMB_ASSERT_ARRAY(r_u->num_als_usrs, r_u->num_als_usrs2);
+
+               for (i = 0; i < r_u->num_als_usrs2; i++)
+               {
+                       prs_grow(ps);
+                       slprintf(tmp, sizeof(tmp) - 1, "als_usrs[%02d]  ", i);
+                       prs_uint32(tmp, ps, depth, &(r_u->num_als_usrs[i]));
+               }
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_samr_q_open_user(SAMR_Q_OPEN_USER *q_u,
+                               POLICY_HND *pol,
+                               uint32 unk_0, uint32 rid)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("samr_make_q_open_user\n"));
+
+       memcpy(&q_u->domain_pol, pol, sizeof(q_u->domain_pol));
+       
+       q_u->unknown_0 = unk_0;
+       q_u->user_rid  = rid;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_open_user(char *desc,  SAMR_Q_OPEN_USER *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_open_user");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("domain_pol", &(q_u->domain_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("unknown_0", ps, depth, &(q_u->unknown_0));
+       prs_uint32("user_rid ", ps, depth, &(q_u->user_rid ));
+
+       prs_align(ps);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_open_user(char *desc,  SAMR_R_OPEN_USER *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_open_user");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("user_pol", &(r_u->user_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+makes a SAMR_Q_QUERY_USERGROUPS structure.
+********************************************************************/
+void make_samr_q_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
+                               POLICY_HND *hnd)
+{
+       if (q_u == NULL || hnd == NULL) return;
+
+       DEBUG(5,("make_samr_q_query_usergroups\n"));
+
+       memcpy(&(q_u->pol), hnd, sizeof(q_u->pol));
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_query_usergroups(char *desc,  SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_query_usergroups");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+}
+
+/*******************************************************************
+makes a SAMR_R_QUERY_USERGROUPS structure.
+********************************************************************/
+void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u,
+               uint32 num_gids, DOM_GID *gid, uint32 status)
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_query_usergroups\n"));
+
+       if (status == 0x0)
+       {
+               r_u->ptr_0        = 1;
+               r_u->num_entries  = num_gids;
+               r_u->ptr_1        = 1;
+               r_u->num_entries2 = num_gids;
+
+               r_u->gid = gid;
+       }
+       else
+       {
+               r_u->ptr_0       = 0;
+               r_u->num_entries = 0;
+               r_u->ptr_1       = 0;
+       }
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_query_usergroups(char *desc,  SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth)
+{
+       int i;
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_query_usergroups");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_0       ", ps, depth, &(r_u->ptr_0      ));
+
+       if (r_u->ptr_0 != 0)
+       {
+               prs_uint32("num_entries ", ps, depth, &(r_u->num_entries));
+               prs_uint32("ptr_1       ", ps, depth, &(r_u->ptr_1      ));
+
+               if (r_u->num_entries != 0)
+               {
+                       prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+
+                       for (i = 0; i < r_u->num_entries2; i++)
+                       {
+                               prs_grow(ps);
+                               smb_io_gid("", &(r_u->gid[i]), ps, depth);
+                       }
+               }
+       }
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+makes a SAMR_Q_QUERY_USERINFO structure.
+********************************************************************/
+void make_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
+                               POLICY_HND *hnd, uint16 switch_value)
+{
+       if (q_u == NULL || hnd == NULL) return;
+
+       DEBUG(5,("make_samr_q_query_userinfo\n"));
+
+       memcpy(&(q_u->pol), hnd, sizeof(q_u->pol));
+       q_u->switch_value = switch_value;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_query_userinfo(char *desc,  SAMR_Q_QUERY_USERINFO *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_query_userinfo");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint16("switch_value", ps, depth, &(q_u->switch_value)); /* 0x0015 or 0x0011 */
+
+       prs_align(ps);
+}
+
+/*******************************************************************
+reads or writes a LOGON_HRS structure.
+********************************************************************/
+static void sam_io_logon_hrs(char *desc,  LOGON_HRS *hrs, prs_struct *ps, int depth)
+{
+       if (hrs == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_logon_hrs");
+       depth++;
+
+       prs_align(ps);
+       
+       prs_uint32 (       "len  ", ps, depth, &(hrs->len ));
+
+       if (hrs->len > 64)
+       {
+               DEBUG(5,("sam_io_logon_hrs: truncating length\n"));
+               hrs->len = 64;
+       }
+
+       prs_uint8s (False, "hours", ps, depth, hrs->hours, hrs->len);
+}
+
+/*******************************************************************
+makes a SAM_USER_INFO_10 structure.
+********************************************************************/
+void make_sam_user_info10(SAM_USER_INFO_10 *usr,
+                               uint32 acb_info)
+{
+       if (usr == NULL) return;
+
+       DEBUG(5,("make_sam_user_info10\n"));
+
+       usr->acb_info = acb_info;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void sam_io_user_info10(char *desc,  SAM_USER_INFO_10 *usr, prs_struct *ps, int depth)
+{
+       if (usr == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_user_info10");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("acb_info", ps, depth, &(usr->acb_info));
+}
+
+/*******************************************************************
+makes a SAM_USER_INFO_11 structure.
+********************************************************************/
+void make_sam_user_info11(SAM_USER_INFO_11 *usr,
+                               NTTIME *expiry,
+                               char *mach_acct,
+                               uint32 rid_user,
+                               uint32 rid_group,
+                               uint16 acct_ctrl)
+                               
+{
+       int len_mach_acct;
+       if (usr == NULL || expiry == NULL || mach_acct == NULL) return;
+
+       DEBUG(5,("make_sam_user_info11\n"));
+
+       len_mach_acct = strlen(mach_acct);
+
+       memcpy(&(usr->expiry),expiry, sizeof(usr->expiry)); /* expiry time or something? */
+       memset((char *)usr->padding_1, '\0', sizeof(usr->padding_1)); /* 0 - padding 24 bytes */
+
+       make_uni_hdr(&(usr->hdr_mach_acct), len_mach_acct, len_mach_acct, 4);  /* unicode header for machine account */
+       usr->padding_2 = 0;               /* 0 - padding 4 bytes */
+
+       usr->ptr_1        = 1;            /* pointer */
+       memset((char *)usr->padding_3, '\0', sizeof(usr->padding_3)); /* 0 - padding 32 bytes */
+       usr->padding_4    = 0;            /* 0 - padding 4 bytes */
+
+       usr->ptr_2        = 1;            /* pointer */
+       usr->padding_5    = 0;            /* 0 - padding 4 bytes */
+
+       usr->ptr_3        = 1;          /* pointer */
+       memset((char *)usr->padding_6, '\0', sizeof(usr->padding_6)); /* 0 - padding 32 bytes */
+
+       usr->rid_user     = rid_user; 
+       usr->rid_group    = rid_group;
+
+       usr->acct_ctrl    = acct_ctrl;
+       usr->unknown_3    = 0x0000;
+
+       usr->unknown_4    = 0x003f;       /* 0x003f      - 16 bit unknown */
+       usr->unknown_5    = 0x003c;       /* 0x003c      - 16 bit unknown */
+
+       memset((char *)usr->padding_7, '\0', sizeof(usr->padding_7)); /* 0 - padding 16 bytes */
+       usr->padding_8    = 0;            /* 0 - padding 4 bytes */
+       
+       make_unistr2(&(usr->uni_mach_acct), mach_acct, len_mach_acct);  /* unicode string for machine account */
+
+       memset((char *)usr->padding_9, '\0', sizeof(usr->padding_9)); /* 0 - padding 48 bytes */
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void sam_io_user_info11(char *desc,  SAM_USER_INFO_11 *usr, prs_struct *ps, int depth)
+{
+       if (usr == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_unknown_24");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint8s (False, "padding_0", ps, depth, usr->padding_0, sizeof(usr->padding_0)); 
+
+       smb_io_time("time", &(usr->expiry), ps, depth); 
+
+       prs_uint8s (False, "padding_1", ps, depth, usr->padding_1, sizeof(usr->padding_1));
+
+       smb_io_unihdr ("unihdr", &(usr->hdr_mach_acct), ps, depth); 
+       prs_uint32(        "padding_2", ps, depth, &(usr->padding_2));
+
+       prs_uint32(        "ptr_1    ", ps, depth, &(usr->ptr_1    ));
+       prs_uint8s (False, "padding_3", ps, depth, usr->padding_3, sizeof(usr->padding_3));
+       prs_uint32(        "padding_4", ps, depth, &(usr->padding_4));
+
+       prs_uint32(        "ptr_2    ", ps, depth, &(usr->ptr_2    ));
+       prs_uint32(        "padding_5", ps, depth, &(usr->padding_5));
+
+       prs_uint32(        "ptr_3    ", ps, depth, &(usr->ptr_3    ));
+       prs_uint8s (False, "padding_6", ps, depth, usr->padding_6, sizeof(usr->padding_6));
+
+       prs_uint32(        "rid_user ", ps, depth, &(usr->rid_user ));
+       prs_uint32(        "rid_group", ps, depth, &(usr->rid_group));
+       prs_uint16(        "acct_ctrl", ps, depth, &(usr->acct_ctrl));
+       prs_uint16(        "unknown_3", ps, depth, &(usr->unknown_3));
+       prs_uint16(        "unknown_4", ps, depth, &(usr->unknown_4));
+       prs_uint16(        "unknown_5", ps, depth, &(usr->unknown_5));
+
+       prs_uint8s (False, "padding_7", ps, depth, usr->padding_7, sizeof(usr->padding_7));
+       prs_uint32(        "padding_8", ps, depth, &(usr->padding_8));
+       
+       smb_io_unistr2("unistr2", &(usr->uni_mach_acct), True, ps, depth); 
+       prs_align(ps);
+
+       prs_uint8s (False, "padding_9", ps, depth, usr->padding_9, sizeof(usr->padding_9));
+}
+/*************************************************************************
+ make_sam_user_info21
+
+ unknown_3 = 0x00ff ffff
+ unknown_5 = 0x0002 0000
+ unknown_6 = 0x0000 04ec 
+
+ *************************************************************************/
+void make_sam_user_info21(SAM_USER_INFO_21 *usr,
+
+       NTTIME *logon_time,
+       NTTIME *logoff_time,
+       NTTIME *kickoff_time,
+       NTTIME *pass_last_set_time,
+       NTTIME *pass_can_change_time,
+       NTTIME *pass_must_change_time,
+
+       char *user_name,
+       char *full_name,
+       char *home_dir,
+       char *dir_drive,
+       char *logon_script,
+       char *profile_path,
+       char *description,
+       char *workstations,
+       char *unknown_str,
+       char *munged_dial,
+
+       uint32 user_rid,
+       uint32 group_rid,
+       uint16 acb_info, 
+
+       uint32 unknown_3,
+       uint16 logon_divs,
+       LOGON_HRS *hrs,
+       uint32 unknown_5,
+       uint32 unknown_6)
+{
+       int len_user_name    = user_name    != NULL ? strlen(user_name   ) : 0;
+       int len_full_name    = full_name    != NULL ? strlen(full_name   ) : 0;
+       int len_home_dir     = home_dir     != NULL ? strlen(home_dir    ) : 0;
+       int len_dir_drive    = dir_drive    != NULL ? strlen(dir_drive   ) : 0;
+       int len_logon_script = logon_script != NULL ? strlen(logon_script) : 0;
+       int len_profile_path = profile_path != NULL ? strlen(profile_path) : 0;
+       int len_description  = description  != NULL ? strlen(description ) : 0;
+       int len_workstations = workstations != NULL ? strlen(workstations) : 0;
+       int len_unknown_str  = unknown_str  != NULL ? strlen(unknown_str ) : 0;
+       int len_munged_dial  = munged_dial  != NULL ? strlen(munged_dial ) : 0;
+
+       usr->logon_time            = *logon_time;
+       usr->logoff_time           = *logoff_time;
+       usr->kickoff_time          = *kickoff_time;
+       usr->pass_last_set_time    = *pass_last_set_time;
+       usr->pass_can_change_time  = *pass_can_change_time;
+       usr->pass_must_change_time = *pass_must_change_time;
+
+       make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 1);
+       make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 1);
+       make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 1);
+       make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 1);
+       make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 1);
+       make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 1);
+       make_uni_hdr(&(usr->hdr_acct_desc   ), len_description , len_description , 1);
+       make_uni_hdr(&(usr->hdr_workstations), len_workstations, len_workstations, 1);
+       make_uni_hdr(&(usr->hdr_unknown_str ), len_unknown_str , len_unknown_str , 1);
+       make_uni_hdr(&(usr->hdr_munged_dial ), len_munged_dial , len_munged_dial , 1);
+
+       memset((char *)usr->nt_pwd, '\0', sizeof(usr->nt_pwd));
+       memset((char *)usr->lm_pwd, '\0', sizeof(usr->lm_pwd));
+
+       usr->user_rid  = user_rid;
+       usr->group_rid = group_rid;
+       usr->acb_info = acb_info;
+       usr->unknown_3 = unknown_3; /* 0x00ff ffff */
+
+       usr->logon_divs = logon_divs; /* should be 168 (hours/week) */
+       usr->ptr_logon_hrs = hrs ? 1 : 0;
+       usr->unknown_5 = unknown_5; /* 0x0002 0000 */
+
+       memset((char *)usr->padding1, '\0', sizeof(usr->padding1));
+
+       make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   );
+       make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   );
+       make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    );
+       make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   );
+       make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script);
+       make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path);
+       make_unistr2(&(usr->uni_acct_desc ), description , len_description );
+       make_unistr2(&(usr->uni_workstations), workstations, len_workstations);
+       make_unistr2(&(usr->uni_unknown_str ), unknown_str , len_unknown_str );
+       make_unistr2(&(usr->uni_munged_dial ), munged_dial , len_munged_dial );
+
+       usr->unknown_6 = unknown_6; /* 0x0000 04ec */
+       usr->padding4 = 0;
+
+       if (hrs)
+       {
+               memcpy(&(usr->logon_hrs), hrs, sizeof(usr->logon_hrs));
+       }
+       else
+       {
+               memset(&(usr->logon_hrs), 0xff, sizeof(usr->logon_hrs));
+       }
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void sam_io_user_info21(char *desc,  SAM_USER_INFO_21 *usr, prs_struct *ps, int depth)
+{
+       if (usr == NULL) return;
+
+       prs_debug(ps, depth, desc, "lsa_io_user_info");
+       depth++;
+
+       prs_align(ps);
+       
+       smb_io_time("logon_time           ", &(usr->logon_time)           , ps, depth);
+       smb_io_time("logoff_time          ", &(usr->logoff_time)          , ps, depth); 
+       smb_io_time("kickoff_time         ", &(usr->kickoff_time)         , ps, depth); 
+       smb_io_time("pass_last_set_time   ", &(usr->pass_last_set_time)   , ps, depth); 
+       smb_io_time("pass_can_change_time ", &(usr->pass_can_change_time) , ps, depth); 
+       smb_io_time("pass_must_change_time", &(usr->pass_must_change_time), ps, depth); 
+
+       smb_io_unihdr("hdr_user_name   ", &(usr->hdr_user_name)   , ps, depth); /* username unicode string header */
+       smb_io_unihdr("hdr_full_name   ", &(usr->hdr_full_name)   , ps, depth); /* user's full name unicode string header */
+       smb_io_unihdr("hdr_home_dir    ", &(usr->hdr_home_dir)    , ps, depth); /* home directory unicode string header */
+       smb_io_unihdr("hdr_dir_drive   ", &(usr->hdr_dir_drive)   , ps, depth); /* home directory drive */
+       smb_io_unihdr("hdr_logon_script", &(usr->hdr_logon_script), ps, depth); /* logon script unicode string header */
+       smb_io_unihdr("hdr_profile_path", &(usr->hdr_profile_path), ps, depth); /* profile path unicode string header */
+       smb_io_unihdr("hdr_acct_desc   ", &(usr->hdr_acct_desc  ) , ps, depth); /* account description */
+       smb_io_unihdr("hdr_workstations", &(usr->hdr_workstations), ps, depth); /* workstations user can log on from */
+       smb_io_unihdr("hdr_unknown_str ", &(usr->hdr_unknown_str ), ps, depth); /* unknown string */
+       smb_io_unihdr("hdr_munged_dial ", &(usr->hdr_munged_dial ), ps, depth); /* workstations user can log on from */
+
+       prs_uint8s (False, "lm_pwd        ", ps, depth, usr->lm_pwd   , sizeof(usr->lm_pwd   ));
+       prs_uint8s (False, "nt_pwd        ", ps, depth, usr->nt_pwd   , sizeof(usr->nt_pwd   ));
+
+       prs_uint32("user_rid      ", ps, depth, &(usr->user_rid     ));       /* User ID */
+       prs_uint32("group_rid     ", ps, depth, &(usr->group_rid    ));      /* Group ID */
+       prs_uint16("acb_info      ", ps, depth, &(usr->acb_info     ));      /* Group ID */
+       prs_align(ps);
+
+       prs_uint32("unknown_3     ", ps, depth, &(usr->unknown_3    ));
+       prs_uint16("logon_divs    ", ps, depth, &(usr->logon_divs   ));     /* logon divisions per week */
+       prs_align(ps);
+       prs_uint32("ptr_logon_hrs ", ps, depth, &(usr->ptr_logon_hrs));
+       prs_uint32("unknown_5     ", ps, depth, &(usr->unknown_5    ));
+
+       prs_uint8s (False, "padding1      ", ps, depth, usr->padding1, sizeof(usr->padding1));
+
+       /* here begins pointed-to data */
+
+       smb_io_unistr2("uni_user_name   ", &(usr->uni_user_name)   , usr->hdr_user_name   .buffer, ps, depth); /* username unicode string */
+       smb_io_unistr2("uni_full_name   ", &(usr->uni_full_name)   , usr->hdr_full_name   .buffer, ps, depth); /* user's full name unicode string */
+       smb_io_unistr2("uni_home_dir    ", &(usr->uni_home_dir)    , usr->hdr_home_dir    .buffer, ps, depth); /* home directory unicode string */
+       smb_io_unistr2("uni_dir_drive   ", &(usr->uni_dir_drive)   , usr->hdr_dir_drive   .buffer, ps, depth); /* home directory drive unicode string */
+       smb_io_unistr2("uni_logon_script", &(usr->uni_logon_script), usr->hdr_logon_script.buffer, ps, depth); /* logon script unicode string */
+       smb_io_unistr2("uni_profile_path", &(usr->uni_profile_path), usr->hdr_profile_path.buffer, ps, depth); /* profile path unicode string */
+       smb_io_unistr2("uni_acct_desc   ", &(usr->uni_acct_desc   ), usr->hdr_acct_desc   .buffer, ps, depth); /* user description unicode string */
+       smb_io_unistr2("uni_workstations", &(usr->uni_workstations), usr->hdr_workstations.buffer, ps, depth); /* worksations user can log on from */
+       smb_io_unistr2("uni_unknown_str ", &(usr->uni_unknown_str ), usr->hdr_unknown_str .buffer, ps, depth); /* unknown string */
+       smb_io_unistr2("uni_munged_dial ", &(usr->uni_munged_dial ), usr->hdr_munged_dial .buffer, ps, depth); /* worksations user can log on from */
+
+       prs_uint32("unknown_6     ", ps, depth, &(usr->unknown_6  ));
+       prs_uint32("padding4      ", ps, depth, &(usr->padding4   ));
+
+       if (usr->ptr_logon_hrs)
+       {
+               sam_io_logon_hrs("logon_hrs", &(usr->logon_hrs)   , ps, depth);
+               prs_align(ps);
+       }
+}
+
+
+/*******************************************************************
+makes a SAMR_R_QUERY_USERINFO structure.
+********************************************************************/
+void make_samr_r_query_userinfo(SAMR_R_QUERY_USERINFO *r_u,
+                               uint16 switch_value, void *info, uint32 status)
+                               
+{
+       if (r_u == NULL || info == NULL) return;
+
+       DEBUG(5,("make_samr_r_query_userinfo\n"));
+
+       r_u->ptr = 0;
+       r_u->switch_value = 0;
+
+       if (status == 0)
+       {
+               r_u->switch_value = switch_value;
+
+               switch (switch_value)
+               {
+                       case 0x10:
+                       {
+                               r_u->ptr = 1;
+                               r_u->info.id10 = (SAM_USER_INFO_10*)info;
+
+                               break;
+                       }
+
+                       case 0x11:
+                       {
+                               r_u->ptr = 1;
+                               r_u->info.id11 = (SAM_USER_INFO_11*)info;
+
+                               break;
+                       }
+
+                       case 21:
+                       {
+                               r_u->ptr = 1;
+                               r_u->info.id21 = (SAM_USER_INFO_21*)info;
+
+                               break;
+                       }
+
+                       default:
+                       {
+                               DEBUG(4,("make_samr_r_query_aliasinfo: unsupported switch level\n"));
+                               break;
+                       }
+               }
+       }
+
+       r_u->status = status;         /* return status */
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_query_userinfo(char *desc,  SAMR_R_QUERY_USERINFO *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_query_userinfo");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr         ", ps, depth, &(r_u->ptr         ));
+       prs_uint16("switch_value", ps, depth, &(r_u->switch_value));
+       prs_align(ps);
+
+       if (r_u->ptr != 0 && r_u->switch_value != 0)
+       {
+               switch (r_u->switch_value)
+               {
+                       case 0x10:
+                       {
+                               if (r_u->info.id10 != NULL)
+                               {
+                                       sam_io_user_info10("", r_u->info.id10, ps, depth);
+                               }
+                               else
+                               {
+                                       DEBUG(2,("samr_io_r_query_userinfo: info pointer not initialised\n"));
+                                       return;
+                               }
+                               break;
+                       }
+/*
+                       case 0x11:
+                       {
+                               if (r_u->info.id11 != NULL)
+                               {
+                                       sam_io_user_info11("", r_u->info.id11, ps, depth);
+                               }
+                               else
+                               {
+                                       DEBUG(2,("samr_io_r_query_userinfo: info pointer not initialised\n"));
+                                       return;
+                               }
+                               break;
+                       }
+*/
+                       case 21:
+                       {
+                               if (r_u->info.id21 != NULL)
+                               {
+                                       sam_io_user_info21("", r_u->info.id21, ps, depth);
+                               }
+                               else
+                               {
+                                       DEBUG(2,("samr_io_r_query_userinfo: info pointer not initialised\n"));
+                                       return;
+                               }
+                               break;
+                       }
+                       default:
+                       {
+                               DEBUG(2,("samr_io_r_query_userinfo: unknown switch level\n"));
+                               break;
+                       }
+                               
+               }
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_unknown_32(char *desc,  SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_unknown_32");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       prs_align(ps);
+
+       smb_io_unihdr ("", &(q_u->hdr_mach_acct), ps, depth); 
+       smb_io_unistr2("", &(q_u->uni_mach_acct), q_u->hdr_mach_acct.buffer, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("acct_ctrl", ps, depth, &(q_u->acct_ctrl));
+       prs_uint16("unknown_1", ps, depth, &(q_u->unknown_1));
+       prs_uint16("unknown_2", ps, depth, &(q_u->unknown_2));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_unknown_32(char *desc,  SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_unknown_32");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_CONNECT structure.
+********************************************************************/
+void make_samr_q_connect(SAMR_Q_CONNECT *q_u,
+                               char *srv_name, uint32 unknown_0)
+{
+       int len_srv_name = strlen(srv_name);
+
+       if (q_u == NULL) return;
+
+       DEBUG(5,("make_q_connect\n"));
+
+       /* make PDC server name \\server */
+       q_u->ptr_srv_name = len_srv_name > 0 ? 1 : 0; 
+       make_unistr2(&(q_u->uni_srv_name), srv_name, len_srv_name+1);  
+
+       /* example values: 0x0000 0002 */
+       q_u->unknown_0 = unknown_0; 
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_connect(char *desc,  SAMR_Q_CONNECT *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_connect");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_srv_name", ps, depth, &(q_u->ptr_srv_name));
+       smb_io_unistr2("", &(q_u->uni_srv_name), q_u->ptr_srv_name, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("unknown_0   ", ps, depth, &(q_u->unknown_0   ));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_connect(char *desc,  SAMR_R_CONNECT *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_connect");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("connect_pol", &(r_u->connect_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+makes a SAMR_Q_CONNECT_ANON structure.
+********************************************************************/
+void make_samr_q_connect_anon(SAMR_Q_CONNECT_ANON *q_u)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("make_q_connect_anon\n"));
+
+       q_u->ptr       = 1;
+       q_u->unknown_0 = 0x5c; /* server name (?!!) */
+       q_u->unknown_1 = 0x01;
+       q_u->unknown_2 = 0x20;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_connect_anon(char *desc,  SAMR_Q_CONNECT_ANON *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_connect_anon");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr      ", ps, depth, &(q_u->ptr      ));
+       prs_uint16("unknown_0", ps, depth, &(q_u->unknown_0));
+       prs_uint16("unknown_1", ps, depth, &(q_u->unknown_1));
+       prs_uint32("unknown_2", ps, depth, &(q_u->unknown_2));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_connect_anon(char *desc,  SAMR_R_CONNECT_ANON *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_connect_anon");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("connect_pol", &(r_u->connect_pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+makes a SAMR_Q_OPEN_ALIAS structure.
+********************************************************************/
+void make_samr_q_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
+                               uint32 unknown_0, uint32 rid)
+{
+       if (q_u == NULL) return;
+
+       DEBUG(5,("make_q_open_alias\n"));
+
+       /* example values: 0x0000 0008 */
+       q_u->unknown_0 = unknown_0; 
+
+       q_u->rid_alias = rid; 
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_open_alias(char *desc,  SAMR_Q_OPEN_ALIAS *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_open_alias");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("unknown_0", ps, depth, &(q_u->unknown_0));
+       prs_uint32("rid_alias", ps, depth, &(q_u->rid_alias));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_open_alias(char *desc,  SAMR_R_OPEN_ALIAS *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_open_alias");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+/*******************************************************************
+makes a SAMR_Q_UNKNOWN_12 structure.
+********************************************************************/
+void make_samr_q_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
+               POLICY_HND *pol, uint32 rid,
+               uint32 num_gids, uint32 *gid)
+{
+       int i;
+       if (q_u == NULL) return;
+
+       DEBUG(5,("make_samr_r_unknwon_12\n"));
+
+       memcpy(&(q_u->pol), pol, sizeof(*pol));
+
+       q_u->num_gids1 = num_gids;
+       q_u->rid       = rid;
+       q_u->ptr       = 0;
+       q_u->num_gids2 = num_gids;
+
+       for (i = 0; i < num_gids; i++)
+       {
+               q_u->gid[i] = gid[i];
+       }
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_UNKNOWN_21 structure.
+********************************************************************/
+void make_samr_q_unknown_21(SAMR_Q_UNKNOWN_21 *q_c,
+                               POLICY_HND *hnd, uint16 unk_1, uint16 unk_2)
+{
+       if (q_c == NULL || hnd == NULL) return;
+
+       DEBUG(5,("make_samr_q_unknown_21\n"));
+
+       memcpy(&(q_c->group_pol), hnd, sizeof(q_c->group_pol));
+       q_c->unknown_1 = unk_1;
+       q_c->unknown_2 = unk_2;
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_UNKNOWN_13 structure.
+********************************************************************/
+void make_samr_q_unknown_13(SAMR_Q_UNKNOWN_13 *q_c,
+                               POLICY_HND *hnd, uint16 unk_1, uint16 unk_2)
+{
+       if (q_c == NULL || hnd == NULL) return;
+
+       DEBUG(5,("make_samr_q_unknown_13\n"));
+
+       memcpy(&(q_c->alias_pol), hnd, sizeof(q_c->alias_pol));
+       q_c->unknown_1 = unk_1;
+       q_c->unknown_2 = unk_2;
+}
+
+
+/*******************************************************************
+makes a SAMR_Q_UNKNOWN_38 structure.
+********************************************************************/
+void make_samr_q_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, char *srv_name)
+{
+       int len_srv_name = strlen(srv_name);
+
+       if (q_u == NULL) return;
+
+       DEBUG(5,("make_q_unknown_38\n"));
+
+       q_u->ptr = 1;
+       make_uni_hdr(&(q_u->hdr_srv_name), len_srv_name, len_srv_name, len_srv_name != 0);
+       make_unistr2(&(q_u->uni_srv_name), srv_name, len_srv_name);  
+
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_unknown_38(char *desc,  SAMR_Q_UNKNOWN_38 *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_unknown_38");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr", ps, depth, &(q_u->ptr));
+       if (q_u->ptr != 0)
+       {
+               smb_io_unihdr ("", &(q_u->hdr_srv_name), ps, depth); 
+               smb_io_unistr2("", &(q_u->uni_srv_name), q_u->hdr_srv_name.buffer, ps, depth); 
+       }
+}
+
+/*******************************************************************
+makes a SAMR_R_UNKNOWN_38 structure.
+********************************************************************/
+void make_samr_r_unknown_38(SAMR_R_UNKNOWN_38 *r_u)
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_r_unknown_38\n"));
+
+       r_u->unk_0 = 0;
+       r_u->unk_1 = 0;
+       r_u->unk_2 = 0;
+       r_u->unk_3 = 0;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_unknown_38(char *desc,  SAMR_R_UNKNOWN_38 *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_unknown_38");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint16("unk_0", ps, depth, &(r_u->unk_0));
+       prs_align(ps);
+       prs_uint16("unk_1", ps, depth, &(r_u->unk_1));
+       prs_align(ps);
+       prs_uint16("unk_2", ps, depth, &(r_u->unk_2));
+       prs_align(ps);
+       prs_uint16("unk_3", ps, depth, &(r_u->unk_3));
+       prs_align(ps);
+}
+
+/*******************************************************************
+make a SAMR_ENC_PASSWD structure.
+********************************************************************/
+void make_enc_passwd(SAMR_ENC_PASSWD *pwd, char pass[512])
+{
+       if (pwd == NULL) return;
+
+       pwd->ptr = 1;
+       memcpy(pwd->pass, pass, sizeof(pwd->pass)); 
+}
+
+/*******************************************************************
+reads or writes a SAMR_ENC_PASSWD structure.
+********************************************************************/
+void samr_io_enc_passwd(char *desc, SAMR_ENC_PASSWD *pwd, prs_struct *ps, int depth)
+{
+       if (pwd == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_enc_passwd");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr", ps, depth, &(pwd->ptr));
+       prs_uint8s(False, "pwd", ps, depth, pwd->pass, sizeof(pwd->pass)); 
+}
+
+/*******************************************************************
+makes a SAMR_ENC_HASH structure.
+********************************************************************/
+void make_enc_hash(SAMR_ENC_HASH *hsh, uchar hash[16])
+{
+       if (hsh == NULL) return;
+
+       hsh->ptr = 1;
+       memcpy(hsh->hash, hash, sizeof(hsh->hash));
+}
+
+/*******************************************************************
+reads or writes a SAMR_ENC_HASH structure.
+********************************************************************/
+void samr_io_enc_hash(char *desc, SAMR_ENC_HASH *hsh, prs_struct *ps, int depth)
+{
+       if (hsh == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_enc_hash");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr ", ps, depth, &(hsh->ptr));
+       prs_uint8s(False, "hash", ps, depth, hsh->hash, sizeof(hsh->hash)); 
+}
+
+/*******************************************************************
+makes a SAMR_R_UNKNOWN_38 structure.
+********************************************************************/
+void make_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
+                               char *dest_host, char *user_name,
+                               char nt_newpass[516], uchar nt_oldhash[16],
+                               char lm_newpass[516], uchar lm_oldhash[16])
+{
+       int len_dest_host = strlen(dest_host);
+       int len_user_name = strlen(user_name);
+
+       if (q_u == NULL) return;
+
+       DEBUG(5,("make_samr_q_chgpasswd_user\n"));
+
+       q_u->ptr_0 = 1;
+       make_uni_hdr(&(q_u->hdr_dest_host), len_dest_host, len_dest_host, len_dest_host != 0);
+       make_unistr2(&(q_u->uni_dest_host), dest_host, len_dest_host);  
+       make_uni_hdr(&(q_u->hdr_user_name), len_user_name, len_user_name, len_user_name != 0);
+       make_unistr2(&(q_u->uni_user_name), user_name, len_user_name);  
+
+       make_enc_passwd(&(q_u->nt_newpass), nt_newpass);
+       make_enc_hash  (&(q_u->nt_oldhash), nt_oldhash);
+
+       q_u->unknown = 0x01;
+
+       make_enc_passwd(&(q_u->lm_newpass), lm_newpass);
+       make_enc_hash  (&(q_u->lm_oldhash), lm_oldhash);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_chgpasswd_user(char *desc, SAMR_Q_CHGPASSWD_USER *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_chgpasswd_user");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_0", ps, depth, &(q_u->ptr_0));
+
+       smb_io_unihdr ("", &(q_u->hdr_dest_host), ps, depth); 
+       smb_io_unistr2("", &(q_u->uni_dest_host), q_u->hdr_dest_host.buffer, ps, depth); 
+       smb_io_unihdr ("", &(q_u->hdr_user_name), ps, depth); 
+       smb_io_unistr2("", &(q_u->uni_user_name), q_u->hdr_user_name.buffer, ps, depth); 
+
+       samr_io_enc_passwd("nt_newpass", &(q_u->nt_newpass), ps, depth); 
+       prs_grow(ps);
+       samr_io_enc_hash  ("nt_oldhash", &(q_u->nt_oldhash), ps, depth); 
+
+       prs_uint32("unknown", ps, depth, &(q_u->unknown));
+
+       samr_io_enc_passwd("lm_newpass", &(q_u->lm_newpass), ps, depth); 
+       prs_grow(ps);
+       samr_io_enc_hash  ("lm_oldhash", &(q_u->lm_oldhash), ps, depth); 
+}
+
+/*******************************************************************
+makes a SAMR_R_CHGPASSWD_USER structure.
+********************************************************************/
+void make_samr_r_chgpasswd_user(SAMR_R_CHGPASSWD_USER *r_u, uint32 status)
+{
+       if (r_u == NULL) return;
+
+       DEBUG(5,("make_r_chgpasswd_user\n"));
+
+       r_u->status = status;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_chgpasswd_user(char *desc, SAMR_R_CHGPASSWD_USER *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_chgpasswd_user");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
+
+
index 96f935cf9b6353524c1e1e87101e6503aa47ab50..56b8be2acbfaa859a81639ca3bea0e348f725193 100644 (file)
@@ -371,6 +371,863 @@ void srv_io_r_net_share_enum(char *desc,  SRV_R_NET_SHARE_ENUM *r_n, prs_struct
        prs_uint32("status     ", ps, depth, &(r_n->status));
 }
 
+/*******************************************************************
+ makes a SESS_INFO_0_STR structure
+********************************************************************/
+void make_srv_sess_info0_str(SESS_INFO_0_STR *ss0, char *name)
+{
+       if (ss0 == NULL) return;
+
+       DEBUG(5,("make_srv_sess_info0_str\n"));
+
+       make_unistr2(&(ss0->uni_name), name, strlen(name)+1);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_sess_info0_str(char *desc,  SESS_INFO_0_STR *ss0, prs_struct *ps, int depth)
+{
+       if (ss0 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_sess_info0_str");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_unistr2("", &(ss0->uni_name), True, ps, depth); 
+}
+
+/*******************************************************************
+ makes a SESS_INFO_0 structure
+********************************************************************/
+void make_srv_sess_info0(SESS_INFO_0 *ss0, char *name)
+{
+       if (ss0 == NULL) return;
+
+       DEBUG(5,("make_srv_sess_info0: %s\n", name));
+
+       ss0->ptr_name = name != NULL ? 1 : 0;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_sess_info0(char *desc,  SESS_INFO_0 *ss0, prs_struct *ps, int depth)
+{
+       if (ss0 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_sess_info0");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_name", ps, depth, &(ss0->ptr_name));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_sess_info_0(char *desc,  SRV_SESS_INFO_0 *ss0, prs_struct *ps, int depth)
+{
+       if (ss0 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_srv_sess_info_0");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries_read", ps, depth, &(ss0->num_entries_read));
+       prs_uint32("ptr_sess_info", ps, depth, &(ss0->ptr_sess_info));
+
+       if (ss0->ptr_sess_info != 0)
+       {
+               int i;
+               int num_entries = ss0->num_entries_read;
+               if (num_entries > MAX_SESS_ENTRIES)
+               {
+                       num_entries = MAX_SESS_ENTRIES; /* report this! */
+               }
+
+               prs_uint32("num_entries_read2", ps, depth, &(ss0->num_entries_read2));
+
+               SMB_ASSERT_ARRAY(ss0->info_0, num_entries);
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_sess_info0("", &(ss0->info_0[i]), ps, depth); 
+               }
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_sess_info0_str("", &(ss0->info_0_str[i]), ps, depth); 
+               }
+
+               prs_align(ps);
+       }
+}
+
+/*******************************************************************
+ makes a SESS_INFO_1_STR structure
+********************************************************************/
+void make_srv_sess_info1_str(SESS_INFO_1_STR *ss1, char *name, char *user)
+{
+       if (ss1 == NULL) return;
+
+       DEBUG(5,("make_srv_sess_info1_str\n"));
+
+       make_unistr2(&(ss1->uni_name), name, strlen(name)+1);
+       make_unistr2(&(ss1->uni_user), name, strlen(user)+1);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_sess_info1_str(char *desc,  SESS_INFO_1_STR *ss1, prs_struct *ps, int depth)
+{
+       if (ss1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_sess_info1_str");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_unistr2("", &(ss1->uni_name), True, ps, depth); 
+       smb_io_unistr2("", &(ss1->uni_user), True, ps, depth); 
+}
+
+/*******************************************************************
+ makes a SESS_INFO_1 structure
+********************************************************************/
+void make_srv_sess_info1(SESS_INFO_1 *ss1, 
+                               char *name, char *user,
+                               uint32 num_opens, uint32 open_time, uint32 idle_time,
+                               uint32 user_flags)
+{
+       if (ss1 == NULL) return;
+
+       DEBUG(5,("make_srv_sess_info1: %s\n", name));
+
+       ss1->ptr_name = name != NULL ? 1 : 0;
+       ss1->ptr_user = user != NULL ? 1 : 0;
+
+       ss1->num_opens  = num_opens;
+       ss1->open_time  = open_time;
+       ss1->idle_time  = idle_time;
+       ss1->user_flags = user_flags;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_sess_info1(char *desc,  SESS_INFO_1 *ss1, prs_struct *ps, int depth)
+{
+       if (ss1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_sess_info1");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_name  ", ps, depth, &(ss1->ptr_name  ));
+       prs_uint32("ptr_user  ", ps, depth, &(ss1->ptr_user  ));
+
+       prs_uint32("num_opens ", ps, depth, &(ss1->num_opens ));
+       prs_uint32("open_time ", ps, depth, &(ss1->open_time ));
+       prs_uint32("idle_time ", ps, depth, &(ss1->idle_time ));
+       prs_uint32("user_flags", ps, depth, &(ss1->user_flags));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_sess_info_1(char *desc,  SRV_SESS_INFO_1 *ss1, prs_struct *ps, int depth)
+{
+       if (ss1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_srv_sess_info_1");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries_read", ps, depth, &(ss1->num_entries_read));
+       prs_uint32("ptr_sess_info", ps, depth, &(ss1->ptr_sess_info));
+
+       if (ss1->ptr_sess_info != 0)
+       {
+               int i;
+               int num_entries = ss1->num_entries_read;
+               if (num_entries > MAX_SESS_ENTRIES)
+               {
+                       num_entries = MAX_SESS_ENTRIES; /* report this! */
+               }
+
+               prs_uint32("num_entries_read2", ps, depth, &(ss1->num_entries_read2));
+
+               SMB_ASSERT_ARRAY(ss1->info_1, num_entries);
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_sess_info1("", &(ss1->info_1[i]), ps, depth); 
+               }
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_sess_info1_str("", &(ss1->info_1_str[i]), ps, depth); 
+               }
+
+               prs_align(ps);
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_sess_ctr(char *desc,  SRV_SESS_INFO_CTR *ctr, prs_struct *ps, int depth)
+{
+       if (ctr == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_srv_sess_ctr");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("switch_value", ps, depth, &(ctr->switch_value));
+       prs_uint32("ptr_sess_ctr", ps, depth, &(ctr->ptr_sess_ctr));
+
+       if (ctr->ptr_sess_ctr != 0)
+       {
+               switch (ctr->switch_value)
+               {
+                       case 0:
+                       {
+                               srv_io_srv_sess_info_0("", &(ctr->sess.info0), ps, depth); 
+                               break;
+                       }
+                       case 1:
+                       {
+                               srv_io_srv_sess_info_1("", &(ctr->sess.info1), ps, depth); 
+                               break;
+                       }
+                       default:
+                       {
+                               DEBUG(5,("%s no session info at switch_value %d\n",
+                                        tab_depth(depth), ctr->switch_value));
+                               break;
+                       }
+               }
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, 
+                               char *srv_name, char *qual_name,
+                               uint32 sess_level, SRV_SESS_INFO_CTR *ctr,
+                               uint32 preferred_len,
+                               ENUM_HND *hnd)
+{
+       if (q_n == NULL || ctr == NULL || hnd == NULL) return;
+
+       q_n->ctr = ctr;
+
+       DEBUG(5,("make_q_net_sess_enum\n"));
+
+       make_buf_unistr2(&(q_n->uni_srv_name), &(q_n->ptr_srv_name), srv_name);
+       make_buf_unistr2(&(q_n->uni_qual_name), &(q_n->ptr_qual_name), qual_name);
+
+       q_n->sess_level    = sess_level;
+       q_n->preferred_len = preferred_len;
+
+       memcpy(&(q_n->enum_hnd), hnd, sizeof(*hnd));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void srv_io_q_net_sess_enum(char *desc,  SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth)
+{
+       if (q_n == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_sess_enum");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_srv_name", ps, depth, &(q_n->ptr_srv_name));
+       smb_io_unistr2("", &(q_n->uni_srv_name), True, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("ptr_qual_name", ps, depth, &(q_n->ptr_qual_name));
+       smb_io_unistr2("", &(q_n->uni_qual_name), q_n->ptr_qual_name, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("sess_level", ps, depth, &(q_n->sess_level  ));
+       
+       if (q_n->sess_level != -1)
+       {
+               srv_io_srv_sess_ctr("sess_ctr", q_n->ctr, ps, depth);
+       }
+
+       prs_uint32("preferred_len", ps, depth, &(q_n->preferred_len));
+
+       smb_io_enum_hnd("enum_hnd", &(q_n->enum_hnd), ps, depth); 
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void srv_io_r_net_sess_enum(char *desc,  SRV_R_NET_SESS_ENUM *r_n, prs_struct *ps, int depth)
+{
+       if (r_n == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_r_net_sess_enum");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("sess_level", ps, depth, &(r_n->sess_level));
+
+       if (r_n->sess_level != -1)
+       {
+               srv_io_srv_sess_ctr("sess_ctr", r_n->ctr, ps, depth);
+       }
+
+       prs_uint32("total_entries", ps, depth, &(r_n->total_entries));
+       smb_io_enum_hnd("enum_hnd", &(r_n->enum_hnd), ps, depth); 
+       prs_uint32("status     ", ps, depth, &(r_n->status));
+}
+
+/*******************************************************************
+ makes a CONN_INFO_0 structure
+********************************************************************/
+void make_srv_conn_info0(CONN_INFO_0 *ss0, uint32 id)
+{
+       if (ss0 == NULL) return;
+
+       DEBUG(5,("make_srv_conn_info0\n"));
+
+       ss0->id = id;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_conn_info0(char *desc,  CONN_INFO_0 *ss0, prs_struct *ps, int depth)
+{
+       if (ss0 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_conn_info0");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("id", ps, depth, &(ss0->id));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_conn_info_0(char *desc,  SRV_CONN_INFO_0 *ss0, prs_struct *ps, int depth)
+{
+       if (ss0 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_srv_conn_info_0");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries_read", ps, depth, &(ss0->num_entries_read));
+       prs_uint32("ptr_conn_info", ps, depth, &(ss0->ptr_conn_info));
+
+       if (ss0->ptr_conn_info != 0)
+       {
+               int i;
+               int num_entries = ss0->num_entries_read;
+               if (num_entries > MAX_CONN_ENTRIES)
+               {
+                       num_entries = MAX_CONN_ENTRIES; /* report this! */
+               }
+
+               prs_uint32("num_entries_read2", ps, depth, &(ss0->num_entries_read2));
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_conn_info0("", &(ss0->info_0[i]), ps, depth); 
+               }
+
+               prs_align(ps);
+       }
+}
+
+/*******************************************************************
+ makes a CONN_INFO_1_STR structure
+********************************************************************/
+void make_srv_conn_info1_str(CONN_INFO_1_STR *ss1, char *usr_name, char *net_name)
+{
+       if (ss1 == NULL) return;
+
+       DEBUG(5,("make_srv_conn_info1_str\n"));
+
+       make_unistr2(&(ss1->uni_usr_name), usr_name, strlen(usr_name)+1);
+       make_unistr2(&(ss1->uni_net_name), net_name, strlen(net_name)+1);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_conn_info1_str(char *desc,  CONN_INFO_1_STR *ss1, prs_struct *ps, int depth)
+{
+       if (ss1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_conn_info1_str");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_unistr2("", &(ss1->uni_usr_name), True, ps, depth); 
+       smb_io_unistr2("", &(ss1->uni_net_name), True, ps, depth); 
+}
+
+/*******************************************************************
+ makes a CONN_INFO_1 structure
+********************************************************************/
+void make_srv_conn_info1(CONN_INFO_1 *ss1, 
+                               uint32 id, uint32 type,
+                               uint32 num_opens, uint32 num_users, uint32 open_time,
+                               char *usr_name, char *net_name)
+{
+       if (ss1 == NULL) return;
+
+       DEBUG(5,("make_srv_conn_info1: %s %s\n", usr_name, net_name));
+
+       ss1->id        = id       ;
+       ss1->type      = type     ;
+       ss1->num_opens = num_opens ;
+       ss1->num_users = num_users;
+       ss1->open_time = open_time;
+
+       ss1->ptr_usr_name = usr_name != NULL ? 1 : 0;
+       ss1->ptr_net_name = net_name != NULL ? 1 : 0;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_conn_info1(char *desc,  CONN_INFO_1 *ss1, prs_struct *ps, int depth)
+{
+       if (ss1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_conn_info1");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("id          ", ps, depth, &(ss1->id        ));
+       prs_uint32("type        ", ps, depth, &(ss1->type      ));
+       prs_uint32("num_opens   ", ps, depth, &(ss1->num_opens ));
+       prs_uint32("num_users   ", ps, depth, &(ss1->num_users ));
+       prs_uint32("open_time   ", ps, depth, &(ss1->open_time ));
+
+       prs_uint32("ptr_usr_name", ps, depth, &(ss1->ptr_usr_name));
+       prs_uint32("ptr_net_name", ps, depth, &(ss1->ptr_net_name));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_conn_info_1(char *desc,  SRV_CONN_INFO_1 *ss1, prs_struct *ps, int depth)
+{
+       if (ss1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_srv_conn_info_1");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries_read", ps, depth, &(ss1->num_entries_read));
+       prs_uint32("ptr_conn_info", ps, depth, &(ss1->ptr_conn_info));
+
+       if (ss1->ptr_conn_info != 0)
+       {
+               int i;
+               int num_entries = ss1->num_entries_read;
+               if (num_entries > MAX_CONN_ENTRIES)
+               {
+                       num_entries = MAX_CONN_ENTRIES; /* report this! */
+               }
+
+               prs_uint32("num_entries_read2", ps, depth, &(ss1->num_entries_read2));
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_conn_info1("", &(ss1->info_1[i]), ps, depth); 
+               }
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_conn_info1_str("", &(ss1->info_1_str[i]), ps, depth); 
+               }
+
+               prs_align(ps);
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_conn_ctr(char *desc,  SRV_CONN_INFO_CTR *ctr, prs_struct *ps, int depth)
+{
+       if (ctr == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_srv_conn_ctr");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("switch_value", ps, depth, &(ctr->switch_value));
+       prs_uint32("ptr_conn_ctr", ps, depth, &(ctr->ptr_conn_ctr));
+
+       if (ctr->ptr_conn_ctr != 0)
+       {
+               switch (ctr->switch_value)
+               {
+                       case 0:
+                       {
+                               srv_io_srv_conn_info_0("", &(ctr->conn.info0), ps, depth); 
+                               break;
+                       }
+                       case 1:
+                       {
+                               srv_io_srv_conn_info_1("", &(ctr->conn.info1), ps, depth); 
+                               break;
+                       }
+                       default:
+                       {
+                               DEBUG(5,("%s no connection info at switch_value %d\n",
+                                        tab_depth(depth), ctr->switch_value));
+                               break;
+                       }
+               }
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_srv_q_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n, 
+                               char *srv_name, char *qual_name,
+                               uint32 conn_level, SRV_CONN_INFO_CTR *ctr,
+                               uint32 preferred_len,
+                               ENUM_HND *hnd)
+{
+       if (q_n == NULL || ctr == NULL || hnd == NULL) return;
+
+       q_n->ctr = ctr;
+
+       DEBUG(5,("make_q_net_conn_enum\n"));
+
+       make_buf_unistr2(&(q_n->uni_srv_name ), &(q_n->ptr_srv_name ), srv_name );
+       make_buf_unistr2(&(q_n->uni_qual_name), &(q_n->ptr_qual_name), qual_name);
+
+       q_n->conn_level    = conn_level;
+       q_n->preferred_len = preferred_len;
+
+       memcpy(&(q_n->enum_hnd), hnd, sizeof(*hnd));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void srv_io_q_net_conn_enum(char *desc,  SRV_Q_NET_CONN_ENUM *q_n, prs_struct *ps, int depth)
+{
+       if (q_n == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_conn_enum");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_srv_name ", ps, depth, &(q_n->ptr_srv_name));
+       smb_io_unistr2("", &(q_n->uni_srv_name), q_n->ptr_srv_name, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("ptr_qual_name", ps, depth, &(q_n->ptr_qual_name));
+       smb_io_unistr2("", &(q_n->uni_qual_name), q_n->ptr_qual_name, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("conn_level", ps, depth, &(q_n->conn_level  ));
+       
+       if (q_n->conn_level != -1)
+       {
+               srv_io_srv_conn_ctr("conn_ctr", q_n->ctr, ps, depth);
+       }
+
+       prs_uint32("preferred_len", ps, depth, &(q_n->preferred_len));
+
+       smb_io_enum_hnd("enum_hnd", &(q_n->enum_hnd), ps, depth); 
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void srv_io_r_net_conn_enum(char *desc,  SRV_R_NET_CONN_ENUM *r_n, prs_struct *ps, int depth)
+{
+       if (r_n == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_r_net_conn_enum");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("conn_level", ps, depth, &(r_n->conn_level));
+
+       if (r_n->conn_level != -1)
+       {
+               srv_io_srv_conn_ctr("conn_ctr", r_n->ctr, ps, depth);
+       }
+
+       prs_uint32("total_entries", ps, depth, &(r_n->total_entries));
+       smb_io_enum_hnd("enum_hnd", &(r_n->enum_hnd), ps, depth); 
+       prs_uint32("status     ", ps, depth, &(r_n->status));
+}
+
+/*******************************************************************
+ makes a FILE_INFO_3_STR structure
+********************************************************************/
+void make_srv_file_info3_str(FILE_INFO_3_STR *fi3, char *user_name, char *path_name)
+{
+       if (fi3 == NULL) return;
+
+       DEBUG(5,("make_srv_file_info3_str\n"));
+
+       make_unistr2(&(fi3->uni_path_name), path_name, strlen(path_name)+1);
+       make_unistr2(&(fi3->uni_user_name), user_name, strlen(user_name)+1);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_file_info3_str(char *desc,  FILE_INFO_3_STR *sh1, prs_struct *ps, int depth)
+{
+       if (sh1 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_file_info3_str");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_unistr2("", &(sh1->uni_path_name), True, ps, depth); 
+       smb_io_unistr2("", &(sh1->uni_user_name), True, ps, depth); 
+}
+
+/*******************************************************************
+ makes a FILE_INFO_3 structure
+********************************************************************/
+void make_srv_file_info3(FILE_INFO_3 *fl3,
+                               uint32 id, uint32 perms, uint32 num_locks,
+                               char *path_name, char *user_name)
+{
+       if (fl3 == NULL) return;
+
+       DEBUG(5,("make_srv_file_info3: %s %s\n", path_name, user_name));
+
+       fl3->id        = id;    
+       fl3->perms     = perms;
+       fl3->num_locks = num_locks;
+
+       fl3->ptr_path_name = path_name != NULL ? 1 : 0;
+       fl3->ptr_user_name = user_name != NULL ? 1 : 0;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_file_info3(char *desc,  FILE_INFO_3 *fl3, prs_struct *ps, int depth)
+{
+       if (fl3 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_file_info3");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("id           ", ps, depth, &(fl3->id           ));
+       prs_uint32("perms        ", ps, depth, &(fl3->perms        ));
+       prs_uint32("num_locks    ", ps, depth, &(fl3->num_locks    ));
+       prs_uint32("ptr_path_name", ps, depth, &(fl3->ptr_path_name));
+       prs_uint32("ptr_user_name", ps, depth, &(fl3->ptr_user_name));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_file_info_3(char *desc,  SRV_FILE_INFO_3 *fl3, prs_struct *ps, int depth)
+{
+       if (fl3 == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_file_3_fl3");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("num_entries_read", ps, depth, &(fl3->num_entries_read));
+       prs_uint32("ptr_file_fl3", ps, depth, &(fl3->ptr_file_info));
+       if (fl3->ptr_file_info != 0)
+       {
+               int i;
+               int num_entries = fl3->num_entries_read;
+               if (num_entries > MAX_FILE_ENTRIES)
+               {
+                       num_entries = MAX_FILE_ENTRIES; /* report this! */
+               }
+
+               prs_uint32("num_entries_read2", ps, depth, &(fl3->num_entries_read2));
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_file_info3("", &(fl3->info_3[i]), ps, depth); 
+               }
+
+               for (i = 0; i < num_entries; i++)
+               {
+                       prs_grow(ps);
+                       srv_io_file_info3_str("", &(fl3->info_3_str[i]), ps, depth); 
+               }
+
+               prs_align(ps);
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void srv_io_srv_file_ctr(char *desc,  SRV_FILE_INFO_CTR *ctr, prs_struct *ps, int depth)
+{
+       if (ctr == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_srv_file_ctr");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("switch_value", ps, depth, &(ctr->switch_value));
+       prs_uint32("ptr_file_ctr", ps, depth, &(ctr->ptr_file_ctr));
+
+       if (ctr->ptr_file_ctr != 0)
+       {
+               switch (ctr->switch_value)
+               {
+                       case 3:
+                       {
+                               srv_io_srv_file_info_3("", &(ctr->file.info3), ps, depth); 
+                               break;
+                       }
+                       default:
+                       {
+                               DEBUG(5,("%s no file info at switch_value %d\n",
+                                        tab_depth(depth), ctr->switch_value));
+                               break;
+                       }
+               }
+       }
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void make_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, 
+                               char *srv_name, char *qual_name,
+                               uint32 file_level, SRV_FILE_INFO_CTR *ctr,
+                               uint32 preferred_len,
+                               ENUM_HND *hnd)
+{
+       if (q_n == NULL || ctr == NULL || hnd == NULL) return;
+
+       q_n->ctr = ctr;
+
+       DEBUG(5,("make_q_net_file_enum\n"));
+
+       make_buf_unistr2(&(q_n->uni_srv_name), &(q_n->ptr_srv_name), srv_name);
+       make_buf_unistr2(&(q_n->uni_qual_name), &(q_n->ptr_qual_name), qual_name);
+
+       q_n->file_level    = file_level;
+       q_n->preferred_len = preferred_len;
+
+       memcpy(&(q_n->enum_hnd), hnd, sizeof(*hnd));
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void srv_io_q_net_file_enum(char *desc,  SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth)
+{
+       if (q_n == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_file_enum");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr_srv_name", ps, depth, &(q_n->ptr_srv_name));
+       smb_io_unistr2("", &(q_n->uni_srv_name), True, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("ptr_qual_name", ps, depth, &(q_n->ptr_qual_name));
+       smb_io_unistr2("", &(q_n->uni_qual_name), q_n->ptr_qual_name, ps, depth); 
+
+       prs_align(ps);
+
+       prs_uint32("file_level", ps, depth, &(q_n->file_level  ));
+
+       if (q_n->file_level != -1)
+       {
+               srv_io_srv_file_ctr("file_ctr", q_n->ctr, ps, depth);
+       }
+
+       prs_uint32("preferred_len", ps, depth, &(q_n->preferred_len));
+
+       smb_io_enum_hnd("enum_hnd", &(q_n->enum_hnd), ps, depth); 
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void srv_io_r_net_file_enum(char *desc,  SRV_R_NET_FILE_ENUM *r_n, prs_struct *ps, int depth)
+{
+       if (r_n == NULL) return;
+
+       prs_debug(ps, depth, desc, "srv_io_r_net_file_enum");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("file_level", ps, depth, &(r_n->file_level));
+
+       if (r_n->file_level != 0)
+       {
+               srv_io_srv_file_ctr("file_ctr", r_n->ctr, ps, depth);
+       }
+
+       prs_uint32("total_entries", ps, depth, &(r_n->total_entries));
+       smb_io_enum_hnd("enum_hnd", &(r_n->enum_hnd), ps, depth); 
+       prs_uint32("status     ", ps, depth, &(r_n->status));
+}
+
 /*******************************************************************
  makes a SRV_INFO_101 structure.
  ********************************************************************/
index bcbece1f4a631d00f952f1dcfff3a56b9428ba96..5e6e101883c35a59700dd651bf0d5c872cc50842 100644 (file)
@@ -74,6 +74,25 @@ static void lsa_reply_open_policy(prs_struct *rdata)
        lsa_io_r_open_pol("", &r_o, rdata, 0);
 }
 
+/***************************************************************************
+make_dom_query
+ ***************************************************************************/
+static void make_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid)
+{
+       int domlen = strlen(dom_name);
+
+       d_q->uni_dom_max_len = domlen * 2;
+       d_q->uni_dom_str_len = domlen * 2;
+
+       d_q->buffer_dom_name = 4; /* domain buffer pointer */
+       d_q->buffer_dom_sid  = 2; /* domain sid pointer */
+
+       /* this string is supposed to be character short */
+       make_unistr2(&(d_q->uni_domain_name), dom_name, domlen);
+
+       make_dom_sid2(&(d_q->dom_sid), dom_sid);
+}
+
 /***************************************************************************
 lsa_reply_query_info
  ***************************************************************************/
@@ -93,24 +112,6 @@ static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e,
        lsa_io_r_enum_trust_dom("", &r_e, rdata, 0);
 }
 
-/***************************************************************************
-make_dom_query
- ***************************************************************************/
-static void make_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid)
-{
-       int domlen = strlen(dom_name);
-
-       d_q->uni_dom_max_len = domlen * 2;
-       d_q->uni_dom_str_len = domlen * 2;
-
-       d_q->buffer_dom_name = 4; /* domain buffer pointer */
-       d_q->buffer_dom_sid  = 2; /* domain sid pointer */
-
-       /* this string is supposed to be character short */
-       make_unistr2(&(d_q->uni_domain_name), dom_name, domlen);
-
-       make_dom_sid2(&(d_q->dom_sid), dom_sid);
-}
 /***************************************************************************
 lsa_reply_query_info
  ***************************************************************************/
@@ -135,6 +136,173 @@ static void lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata,
 }
 
 
+/***************************************************************************
+make_dom_ref
+ ***************************************************************************/
+static void make_dom_ref(DOM_R_REF *ref, int num_domains,
+                               char **dom_names, DOM_SID **dom_sids)
+                         
+{
+       int i;
+
+       if (num_domains > MAX_REF_DOMAINS)
+       {
+               num_domains = MAX_REF_DOMAINS;
+       }
+
+       ref->undoc_buffer = 1;
+       ref->num_ref_doms_1 = num_domains;
+       ref->undoc_buffer2 = 1;
+       ref->max_entries = MAX_REF_DOMAINS;
+       ref->num_ref_doms_2 = num_domains;
+
+       for (i = 0; i < num_domains; i++)
+       {
+               int len = dom_names[i] != NULL ? strlen(dom_names[i]) : 0;
+
+               make_uni_hdr(&(ref->hdr_ref_dom[i].hdr_dom_name), len, len, len != 0 ? 1 : 0);
+               ref->hdr_ref_dom[i].ptr_dom_sid = dom_sids[i] != NULL ? 1 : 0;
+
+               make_unistr2 (&(ref->ref_dom[i].uni_dom_name), dom_names[i], len);
+               make_dom_sid2(&(ref->ref_dom[i].ref_dom     ), dom_sids [i]);
+       }
+
+}
+
+/***************************************************************************
+make_reply_lookup_rids
+ ***************************************************************************/
+static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
+                               int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
+                               int num_ref_doms,
+                               char **dom_names, DOM_SID **dom_sids)
+{
+       int i;
+
+       make_dom_ref(&(r_l->dom_ref), num_ref_doms, dom_names, dom_sids);
+
+       r_l->num_entries = num_entries;
+       r_l->undoc_buffer = 1;
+       r_l->num_entries2 = num_entries;
+
+       SMB_ASSERT_ARRAY(r_l->dom_rid, num_entries);
+
+       for (i = 0; i < num_entries; i++)
+       {
+               make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i], 0x01);
+       }
+
+       r_l->num_entries3 = num_entries;
+}
+
+/***************************************************************************
+make_lsa_trans_names
+ ***************************************************************************/
+static void make_lsa_trans_names(LSA_TRANS_NAME_ENUM *trn,
+                               int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
+                               uint32 *total)
+{
+       uint32 status = 0x0;
+       int i;
+       (*total) = 0;
+
+       SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
+
+       for (i = 0; i < num_entries; i++)
+       {
+               uint32 rid = 0xffffffff;
+               uint8 num_auths = sid[i].sid.num_auths;
+               fstring name;
+               uint32 type;
+               
+               SMB_ASSERT_ARRAY(sid[i].sid.sub_auths, num_auths);
+
+               /* find the rid to look up */
+               if (num_auths != 0)
+               {
+                       rid = sid[i].sid.sub_auths[num_auths-1];
+
+                       status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
+
+                       status = (status != 0x0) ? lookup_user_name (rid, name, &type) : status;
+                       status = (status != 0x0) ? lookup_group_name(rid, name, &type) : status;
+                       status = (status != 0x0) ? lookup_alias_name(rid, name, &type) : status;
+               }
+
+               if (status == 0x0)
+               {
+                       make_lsa_trans_name(&(trn->name    [(*total)]),
+                                           &(trn->uni_name[(*total)]),
+                                           type, name, (*total));
+                       (*total)++;
+               }
+       }
+
+       trn->num_entries = (*total);
+       trn->ptr_trans_names = 1;
+       trn->num_entries2 = (*total);
+}
+
+/***************************************************************************
+make_reply_lookup_sids
+ ***************************************************************************/
+static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
+                               DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
+                               uint32 mapped_count, uint32 status)
+{
+       r_l->dom_ref      = ref;
+       r_l->names        = names;
+       r_l->mapped_count = mapped_count;
+       r_l->status       = status;
+}
+
+/***************************************************************************
+lsa_reply_lookup_sids
+ ***************************************************************************/
+static void lsa_reply_lookup_sids(prs_struct *rdata,
+                               int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
+                               int num_ref_doms,
+                               char **dom_names, DOM_SID **dom_sids)
+{
+       LSA_R_LOOKUP_SIDS r_l;
+       DOM_R_REF ref;
+       LSA_TRANS_NAME_ENUM names;
+       uint32 mapped_count = 0;
+
+       ZERO_STRUCT(r_l);
+       ZERO_STRUCT(ref);
+       ZERO_STRUCT(names);
+
+       /* set up the LSA Lookup SIDs response */
+       make_dom_ref(&ref, num_ref_doms, dom_names, dom_sids);
+       make_lsa_trans_names(&names, num_entries, sid, &mapped_count);
+       make_reply_lookup_sids(&r_l, &ref, &names, mapped_count, 0x0);
+
+       /* store the response in the SMB stream */
+       lsa_io_r_lookup_sids("", &r_l, rdata, 0);
+}
+
+/***************************************************************************
+lsa_reply_lookup_rids
+ ***************************************************************************/
+static void lsa_reply_lookup_rids(prs_struct *rdata,
+                               int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
+                               int num_ref_doms,
+                               char **dom_names, DOM_SID **dom_sids)
+{
+       LSA_R_LOOKUP_RIDS r_l;
+
+       ZERO_STRUCT(r_l);
+
+       /* set up the LSA Lookup RIDs response */
+       make_reply_lookup_rids(&r_l, num_entries, dom_rids,
+                               num_ref_doms, dom_names, dom_sids);
+       r_l.status = 0x0;
+
+       /* store the response in the SMB stream */
+       lsa_io_r_lookup_rids("", &r_l, rdata, 0);
+}
+
 /***************************************************************************
 api_lsa_open_policy
  ***************************************************************************/
@@ -210,6 +378,130 @@ static void api_lsa_query_info( uint16 vuid, prs_struct *data,
        lsa_reply_query_info(&q_i, rdata, dom_name, &global_sam_sid);
 }
 
+/***************************************************************************
+api_lsa_lookup_sids
+ ***************************************************************************/
+static void api_lsa_lookup_sids( uint16 vuid, prs_struct *data,
+                                 prs_struct *rdata )
+{
+       LSA_Q_LOOKUP_SIDS q_l;
+       pstring dom_name;
+       DOM_SID sid_S_1_1;
+       DOM_SID sid_S_1_3;
+       DOM_SID sid_S_1_5;
+
+       DOM_SID *sid_array[4];
+       char    *dom_names[4];
+
+       ZERO_STRUCT(q_l);
+       ZERO_STRUCT(sid_S_1_1);
+       ZERO_STRUCT(sid_S_1_3);
+       ZERO_STRUCT(sid_S_1_5);
+
+       /* grab the info class and policy handle */
+       lsa_io_q_lookup_sids("", &q_l, data, 0);
+
+       pstrcpy(dom_name, lp_workgroup());
+
+       string_to_sid(&sid_S_1_1, "S-1-1");
+        string_to_sid(&sid_S_1_3, "S-1-3");
+        string_to_sid(&sid_S_1_5, "S-1-5");
+
+       dom_names[0] = dom_name;
+       sid_array[0] = &global_sam_sid;
+
+       dom_names[1] = "Everyone";
+       sid_array[1] = &sid_S_1_1;
+
+       dom_names[2] = "don't know";
+       sid_array[2] = &sid_S_1_3;
+
+       dom_names[3] = "NT AUTHORITY";
+       sid_array[3] = &sid_S_1_5;
+
+       /* construct reply.  return status is always 0x0 */
+       lsa_reply_lookup_sids(rdata,
+                              q_l.sids.num_entries, q_l.sids.sid, /* SIDs */
+                              4, dom_names, sid_array);
+}
+
+/***************************************************************************
+api_lsa_lookup_names
+ ***************************************************************************/
+static void api_lsa_lookup_names( uint16 vuid, prs_struct *data,
+                                  prs_struct *rdata )
+{
+       int i;
+       LSA_Q_LOOKUP_RIDS q_l;
+       pstring dom_name;
+       uint32 dom_rids[MAX_LOOKUP_SIDS];
+       uint32 dummy_g_rid;
+
+       DOM_SID sid_S_1_1;
+       DOM_SID sid_S_1_3;
+       DOM_SID sid_S_1_5;
+
+       DOM_SID *sid_array[4];
+       char    *dom_names[4];
+
+       ZERO_STRUCT(q_l);
+       ZERO_STRUCT(sid_S_1_1);
+       ZERO_STRUCT(sid_S_1_3);
+       ZERO_STRUCT(sid_S_1_5);
+       ZERO_ARRAY(dom_rids);   
+
+       /* grab the info class and policy handle */
+       lsa_io_q_lookup_rids("", &q_l, data, 0);
+
+       pstrcpy(dom_name, lp_workgroup());
+
+       string_to_sid(&sid_S_1_1, "S-1-1");
+        string_to_sid(&sid_S_1_3, "S-1-3");
+        string_to_sid(&sid_S_1_5, "S-1-5");
+
+       dom_names[0] = dom_name;
+       sid_array[0] = &global_sam_sid;
+
+       dom_names[1] = "Everyone";
+       sid_array[1] = &sid_S_1_1;
+
+       dom_names[2] = "don't know";
+       sid_array[2] = &sid_S_1_3;
+
+       dom_names[3] = "NT AUTHORITY";
+       sid_array[3] = &sid_S_1_5;
+
+       SMB_ASSERT_ARRAY(q_l.lookup_name, q_l.num_entries);
+
+       /* convert received RIDs to strings, so we can do them. */
+       for (i = 0; i < q_l.num_entries; i++)
+       {
+               fstring user_name;
+               fstrcpy(user_name, unistr2(q_l.lookup_name[i].str.buffer));
+
+               /*
+                * Map to the UNIX username.
+                */
+               map_username(user_name);
+
+               /*
+                * Do any case conversions.
+                */
+               (void)Get_Pwnam(user_name, True);
+
+               if (!pdb_name_to_rid(user_name, &dom_rids[i], &dummy_g_rid))
+               {
+                       /* WHOOPS!  we should really do something about this... */
+                       dom_rids[i] = 0;
+               }
+       }
+
+       /* construct reply.  return status is always 0x0 */
+       lsa_reply_lookup_rids(rdata,
+                              q_l.num_entries, dom_rids, /* text-converted SIDs */
+                              4, dom_names, sid_array);
+}
+
 /***************************************************************************
  api_lsa_close
  ***************************************************************************/
@@ -271,6 +563,8 @@ static struct api_struct api_lsa_cmds[] =
        { "LSA_ENUMTRUSTDOM"    , LSA_ENUMTRUSTDOM    , api_lsa_enum_trust_dom },
        { "LSA_CLOSE"           , LSA_CLOSE           , api_lsa_close          },
        { "LSA_OPENSECRET"      , LSA_OPENSECRET      , api_lsa_open_secret    },
+       { "LSA_LOOKUPSIDS"      , LSA_LOOKUPSIDS      , api_lsa_lookup_sids    },
+       { "LSA_LOOKUPNAMES"     , LSA_LOOKUPNAMES     , api_lsa_lookup_names   },
        { NULL                  , 0                   , NULL                   }
 };
 
index bbd58dbd278a2019a2b49468304d574d467db79c..e37bc47022cdbde689252e512a3b5a9c0ef518e9 100644 (file)
@@ -340,8 +340,11 @@ struct api_cmd
 static struct api_cmd api_fd_commands[] =
 {
     { "lsarpc",   "lsass",   api_ntlsa_rpc },
+    { "samr",     "lsass",   api_samr_rpc },
     { "srvsvc",   "ntsvcs",  api_srvsvc_rpc },
+    { "wkssvc",   "ntsvcs",  api_wkssvc_rpc },
     { "NETLOGON", "lsass",   api_netlog_rpc },
+    { "winreg",   "winreg",  api_reg_rpc },
     { NULL,       NULL,      NULL }
 };
 
index 87225ae326d81eb0f15da8aa25944b11e889840a..188f8a0bcd1d27815e49ffd67e85bf1b834d3a76 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* removed in SAMBA_2_0 branch. */
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+
+/*******************************************************************
+ reg_reply_unknown_1
+ ********************************************************************/
+static void reg_reply_close(REG_Q_CLOSE *q_r,
+                               prs_struct *rdata)
+{
+       REG_R_CLOSE r_u;
+
+       /* set up the REG unknown_1 response */
+       memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
+
+       /* close the policy handle */
+       if (close_lsa_policy_hnd(&(q_r->pol)))
+       {
+               r_u.status = 0;
+       }
+       else
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
+       }
+
+       DEBUG(5,("reg_unknown_1: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       reg_io_r_close("", &r_u, rdata, 0);
+
+       DEBUG(5,("reg_unknown_1: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_reg_close
+ ********************************************************************/
+static void api_reg_close( uint16 vuid, prs_struct *data,
+                                    prs_struct *rdata )
+{
+       REG_Q_CLOSE q_r;
+
+       /* grab the reg unknown 1 */
+       reg_io_q_close("", &q_r, data, 0);
+
+       /* construct reply.  always indicate success */
+       reg_reply_close(&q_r, rdata);
+}
+
+
+/*******************************************************************
+ reg_reply_open
+ ********************************************************************/
+static void reg_reply_open(REG_Q_OPEN_HKLM *q_r,
+                               prs_struct *rdata)
+{
+       REG_R_OPEN_HKLM r_u;
+
+       r_u.status = 0x0;
+       /* get a (unique) handle.  open a policy on it. */
+       if (r_u.status == 0x0 && !open_lsa_policy_hnd(&(r_u.pol)))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       DEBUG(5,("reg_open: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       reg_io_r_open_hklm("", &r_u, rdata, 0);
+
+       DEBUG(5,("reg_open: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_reg_open
+ ********************************************************************/
+static void api_reg_open( uint16 vuid, prs_struct *data,
+                                    prs_struct *rdata )
+{
+       REG_Q_OPEN_HKLM q_u;
+
+       /* grab the reg open */
+       reg_io_q_open_hklm("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       reg_reply_open(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ reg_reply_open_entry
+ ********************************************************************/
+static void reg_reply_open_entry(REG_Q_OPEN_ENTRY *q_u,
+                               prs_struct *rdata)
+{
+       uint32 status     = 0;
+       POLICY_HND pol;
+       REG_R_OPEN_ENTRY r_u;
+       fstring name;
+
+       DEBUG(5,("reg_open_entry: %d\n", __LINE__));
+
+       if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1)
+       {
+               status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (status == 0x0 && !open_lsa_policy_hnd(&pol))
+       {
+               status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
+       }
+
+       fstrcpy(name, unistrn2(q_u->uni_name.buffer, q_u->uni_name.uni_str_len));
+
+       if (status == 0x0)
+       {
+               DEBUG(5,("reg_open_entry: %s\n", name));
+               /* lkcl XXXX do a check on the name, here */
+       }
+
+       if (status == 0x0 && !set_lsa_policy_reg_name(&pol, name))
+       {
+               status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
+       }
+
+       make_reg_r_open_entry(&r_u, &pol, status);
+
+       /* store the response in the SMB stream */
+       reg_io_r_open_entry("", &r_u, rdata, 0);
+
+       DEBUG(5,("reg_open_entry: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_reg_open_entry
+ ********************************************************************/
+static void api_reg_open_entry( uint16 vuid, prs_struct *data,
+                                    prs_struct *rdata )
+{
+       REG_Q_OPEN_ENTRY q_u;
+
+       /* grab the reg open entry */
+       reg_io_q_open_entry("", &q_u, data, 0);
+
+       /* construct reply. */
+       reg_reply_open_entry(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ reg_reply_info
+ ********************************************************************/
+static void reg_reply_info(REG_Q_INFO *q_u,
+                               prs_struct *rdata)
+{
+       uint32 status     = 0;
+
+       REG_R_INFO r_u;
+
+       DEBUG(5,("reg_info: %d\n", __LINE__));
+
+       if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1)
+       {
+               status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (status == 0)
+       {
+       }
+
+       make_reg_r_info(&r_u, 1, "LanmanNT", 0x12, 0x12, status);
+
+       /* store the response in the SMB stream */
+       reg_io_r_info("", &r_u, rdata, 0);
+
+       DEBUG(5,("reg_open_entry: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_reg_info
+ ********************************************************************/
+static void api_reg_info( uint16 vuid, prs_struct *data,
+                                    prs_struct *rdata )
+{
+       REG_Q_INFO q_u;
+
+       /* grab the reg unknown 0x11*/
+       reg_io_q_info("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       reg_reply_info(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ array of \PIPE\reg operations
+ ********************************************************************/
+static struct api_struct api_reg_cmds[] =
+{
+       { "REG_CLOSE"        , REG_CLOSE        , api_reg_close        },
+       { "REG_OPEN_ENTRY"   , REG_OPEN_ENTRY   , api_reg_open_entry   },
+       { "REG_OPEN"         , REG_OPEN_HKLM    , api_reg_open         },
+       { "REG_INFO"         , REG_INFO         , api_reg_info         },
+       { NULL,                0                , NULL                 }
+};
+
+/*******************************************************************
+ receives a reg pipe and responds.
+ ********************************************************************/
+BOOL api_reg_rpc(pipes_struct *p, prs_struct *data)
+{
+       return api_rpcTNP(p, "api_reg_rpc", api_reg_cmds, data);
+}
+
index 1442f03464b3cd91fd2276672e913a09135f63f1..4867d1aa2ce27d0af8e22598b932e871d01ad0b0 100644 (file)
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* removed in SAMBA_2_0 branch */
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+extern fstring global_myworkgroup;
+extern pstring global_myname;
+extern DOM_SID global_sam_sid;
+
+extern rid_name domain_group_rids[];
+extern rid_name domain_alias_rids[];
+extern rid_name builtin_alias_rids[];
+
+/*******************************************************************
+  This next function should be replaced with something that
+  dynamically returns the correct user info..... JRA.
+ ********************************************************************/
+
+static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf,
+                               int start_idx,
+                                int *total_entries, int *num_entries,
+                                int max_num_entries,
+                                uint16 acb_mask)
+{
+       void *vp = NULL;
+       struct sam_passwd *pwd = NULL;
+
+       (*num_entries) = 0;
+       (*total_entries) = 0;
+
+       if (pw_buf == NULL) return False;
+
+       vp = startsmbpwent(False);
+       if (!vp)
+       {
+               DEBUG(0, ("get_sampwd_entries: Unable to open SMB password database.\n"));
+               return False;
+       }
+
+       while (((pwd = getsam21pwent(vp)) != NULL) && (*num_entries) < max_num_entries)
+       {
+               int user_name_len;
+
+               if (start_idx > 0)
+               {
+                       /* skip the requested number of entries.
+                          not very efficient, but hey...
+                        */
+                       start_idx--;
+                       continue;
+               }
+
+               user_name_len = strlen(pwd->smb_name);
+               make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len);
+               make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len, 
+                              user_name_len, 1);
+               pw_buf[(*num_entries)].user_rid = pwd->user_rid;
+               memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
+
+               /* Now check if the NT compatible password is available. */
+               if (pwd->smb_nt_passwd != NULL)
+               {
+                       memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
+               }
+
+               pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
+
+               DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
+                         (*num_entries), pwd->smb_name,
+                         pwd->user_rid, pwd->acct_ctrl));
+
+               if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask))
+               {
+                       DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
+                       (*num_entries)++;
+               }
+               else
+               {
+                       DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
+               }
+
+               (*total_entries)++;
+       }
+
+       endsmbpwent(vp);
+
+       return (*num_entries) > 0;
+}
+
+/*******************************************************************
+ samr_reply_unknown_1
+ ********************************************************************/
+static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_CLOSE_HND r_u;
+
+       /* set up the SAMR unknown_1 response */
+       memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
+
+       /* close the policy handle */
+       if (close_lsa_policy_hnd(&(q_u->pol)))
+       {
+               r_u.status = 0;
+       }
+       else
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
+       }
+
+       DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_close_hnd("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_close_hnd
+ ********************************************************************/
+static void api_samr_close_hnd( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_CLOSE_HND q_u;
+
+       /* grab the samr unknown 1 */
+       samr_io_q_close_hnd("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_close_hnd(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_open_domain
+ ********************************************************************/
+static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_OPEN_DOMAIN r_u;
+       BOOL pol_open = False;
+
+       r_u.status = 0x0;
+
+       /* find the connection policy handle. */
+       if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* get a (unique) handle.  open a policy on it. */
+       if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       /* associate the domain SID with the (unique) handle. */
+       if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
+       {
+               /* oh, whoops.  don't know what error message to return, here */
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (r_u.status != 0 && pol_open)
+       {
+               close_lsa_policy_hnd(&(r_u.domain_pol));
+       }
+
+       DEBUG(5,("samr_open_domain: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_open_domain("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_open_domain: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_open_domain
+ ********************************************************************/
+static void api_samr_open_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_OPEN_DOMAIN q_u;
+
+       /* grab the samr open */
+       samr_io_q_open_domain("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_open_domain(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_unknown_2c
+ ********************************************************************/
+static void samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_UNKNOWN_2C r_u;
+       uint32 status = 0x0;
+
+       /* find the policy handle.  open a policy on it. */
+       if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
+       {
+               status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* find the user's rid */
+       if ((status == 0x0) && (get_lsa_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff))
+       {
+               status = NT_STATUS_OBJECT_TYPE_MISMATCH;
+       }
+
+       make_samr_r_unknown_2c(&r_u, status);
+
+       DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_unknown_2c("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_unknown_2c
+ ********************************************************************/
+static void api_samr_unknown_2c( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_UNKNOWN_2C q_u;
+
+       /* grab the samr open */
+       samr_io_q_unknown_2c("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_unknown_2c(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_unknown_3
+ ********************************************************************/
+static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_UNKNOWN_3 r_u;
+       DOM_SID3 sid[MAX_SAM_SIDS];
+       uint32 rid;
+       uint32 status;
+
+       status = 0x0;
+
+       /* find the policy handle.  open a policy on it. */
+       if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
+       {
+               status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* find the user's rid */
+       if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
+       {
+               status = NT_STATUS_OBJECT_TYPE_MISMATCH;
+       }
+
+       if (status == 0x0)
+       {
+               DOM_SID user_sid;
+               DOM_SID everyone_sid;
+
+               user_sid = global_sam_sid;
+
+               SMB_ASSERT_ARRAY(user_sid.sub_auths, user_sid.num_auths+1);
+
+               /*
+                * Add the user RID.
+                */
+               user_sid.sub_auths[user_sid.num_auths++] = rid;
+               
+                       string_to_sid(&everyone_sid, "S-1-1");
+
+                       /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */
+                       /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
+                       make_dom_sid3(&(sid[0]), 0x035b, 0x0002, &everyone_sid);
+                       make_dom_sid3(&(sid[1]), 0x0044, 0x0002, &user_sid);
+       }
+
+       make_samr_r_unknown_3(&r_u,
+                               0x0001, 0x8004,
+                               0x00000014, 0x0002, 0x0070,
+                               2, sid, status);
+
+       DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_unknown_3("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_unknown_3
+ ********************************************************************/
+static void api_samr_unknown_3( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_UNKNOWN_3 q_u;
+
+       /* grab the samr open */
+       samr_io_q_unknown_3("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_unknown_3(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_enum_dom_users
+ ********************************************************************/
+static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_ENUM_DOM_USERS r_e;
+       SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
+       int num_entries;
+       int total_entries;
+
+       r_e.status = 0x0;
+       r_e.total_num_entries = 0;
+
+       /* find the policy handle.  open a policy on it. */
+       if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
+
+       become_root(True);
+       get_sampwd_entries(pass, 0, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask);
+       unbecome_root(True);
+
+       make_samr_r_enum_dom_users(&r_e, total_entries,
+                                  q_u->unknown_0, num_entries,
+                                  pass, r_e.status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_enum_dom_users("", &r_e, rdata, 0);
+
+       DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_enum_dom_users
+ ********************************************************************/
+static void api_samr_enum_dom_users( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_ENUM_DOM_USERS q_e;
+
+       /* grab the samr open */
+       samr_io_q_enum_dom_users("", &q_e, data, 0);
+
+       /* construct reply. */
+       samr_reply_enum_dom_users(&q_e, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_enum_dom_groups
+ ********************************************************************/
+static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_ENUM_DOM_GROUPS r_e;
+       SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
+       int num_entries;
+       BOOL got_grps;
+       char *dummy_group = "Domain Admins";
+
+       r_e.status = 0x0;
+       r_e.num_entries = 0;
+
+       /* find the policy handle.  open a policy on it. */
+       if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
+
+       got_grps = True;
+       num_entries = 1;
+       make_unistr2(&(pass[0].uni_user_name), dummy_group, strlen(dummy_group));
+       pass[0].user_rid = DOMAIN_GROUP_RID_ADMINS;
+
+       if (r_e.status == 0 && got_grps)
+       {
+               make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, pass, r_e.status);
+       }
+
+       /* store the response in the SMB stream */
+       samr_io_r_enum_dom_groups("", &r_e, rdata, 0);
+
+       DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_enum_dom_groups
+ ********************************************************************/
+static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_ENUM_DOM_GROUPS q_e;
+
+       /* grab the samr open */
+       samr_io_q_enum_dom_groups("", &q_e, data, 0);
+
+       /* construct reply. */
+       samr_reply_enum_dom_groups(&q_e, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_enum_dom_aliases
+ ********************************************************************/
+static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_ENUM_DOM_ALIASES r_e;
+       SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
+       int num_entries = 0;
+       DOM_SID sid;
+       fstring sid_str;
+       fstring sam_sid_str;
+
+       r_e.status = 0x0;
+       r_e.num_entries = 0;
+
+       /* find the policy handle.  open a policy on it. */
+       if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
+       {
+               r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       sid_to_string(sid_str, &sid);
+       sid_to_string(sam_sid_str, &global_sam_sid);
+
+       DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
+
+       /* well-known aliases */
+       if (strequal(sid_str, "S-1-5-32"))
+       {
+               char *name;
+               while (num_entries < MAX_SAM_ENTRIES && ((name = builtin_alias_rids[num_entries].name) != NULL))
+               {
+                       make_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
+                       pass[num_entries].user_rid = builtin_alias_rids[num_entries].rid;
+                       num_entries++;
+               }
+       }
+       else if (strequal(sid_str, sam_sid_str))
+       {
+               /* local aliases */
+               /* oops!  there's no code to deal with this */
+               DEBUG(3,("samr_reply_enum_dom_aliases: enum of aliases in our domain not supported yet\n"));
+               num_entries = 0;
+       }
+               
+       make_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_enum_dom_aliases("", &r_e, rdata, 0);
+
+       DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_enum_dom_aliases
+ ********************************************************************/
+static void api_samr_enum_dom_aliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_ENUM_DOM_ALIASES q_e;
+
+       /* grab the samr open */
+       samr_io_q_enum_dom_aliases("", &q_e, data, 0);
+
+       /* construct reply. */
+       samr_reply_enum_dom_aliases(&q_e, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_query_dispinfo
+ ********************************************************************/
+static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_QUERY_DISPINFO r_e;
+       SAM_INFO_CTR ctr;
+       SAM_INFO_1 info1;
+       SAM_INFO_2 info2;
+       SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
+       int num_entries = 0;
+       int total_entries = 0;
+       BOOL got_pwds;
+       uint16 switch_level = 0x0;
+
+       ZERO_STRUCT(r_e);
+
+       r_e.status = 0x0;
+
+       DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
+
+       /* find the policy handle.  open a policy on it. */
+       if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+               DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
+       }
+
+       if (r_e.status == 0x0)
+       {
+               become_root(True);
+               got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
+               unbecome_root(True);
+
+               switch (q_u->switch_level)
+               {
+                       case 0x1:
+                       {
+                       
+                               /* query disp info is for users */
+                               switch_level = 0x1;
+                               make_sam_info_1(&info1, ACB_NORMAL,
+                                       q_u->start_idx, num_entries, pass);
+
+                               ctr.sam.info1 = &info1;
+
+                               break;
+                       }
+                       case 0x2:
+                       {
+                               /* query disp info is for servers */
+                               switch_level = 0x2;
+                               make_sam_info_2(&info2, ACB_WSTRUST,
+                                       q_u->start_idx, num_entries, pass);
+
+                               ctr.sam.info2 = &info2;
+
+                               break;
+                       }
+               }
+       }
+
+       if (r_e.status == 0 && got_pwds)
+       {
+               make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
+       }
+
+       /* store the response in the SMB stream */
+       samr_io_r_query_dispinfo("", &r_e, rdata, 0);
+
+       DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_query_dispinfo
+ ********************************************************************/
+static void api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_QUERY_DISPINFO q_e;
+
+       /* grab the samr open */
+       samr_io_q_query_dispinfo("", &q_e, data, 0);
+
+       /* construct reply. */
+       samr_reply_query_dispinfo(&q_e, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_query_aliasinfo
+ ********************************************************************/
+static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_QUERY_ALIASINFO r_e;
+
+       r_e.status = 0x0;
+       r_e.ptr = 0;
+
+       /* find the policy handle.  open a policy on it. */
+       if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
+
+       if (r_e.status == 0x0)
+       {
+               if (q_u->switch_level != 3)
+               {
+                       r_e.status = NT_STATUS_INVALID_INFO_CLASS;
+               }
+       }
+
+       make_samr_r_query_aliasinfo(&r_e, q_u->switch_level,
+                           "<account description>",
+                               r_e.status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_query_aliasinfo("", &r_e, rdata, 0);
+
+       DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_query_aliasinfo
+ ********************************************************************/
+static void api_samr_query_aliasinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_QUERY_ALIASINFO q_e;
+
+       /* grab the samr open */
+       samr_io_q_query_aliasinfo("", &q_e, data, 0);
+
+       /* construct reply. */
+       samr_reply_query_aliasinfo(&q_e, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_lookup_ids
+ ********************************************************************/
+static void samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
+                               prs_struct *rdata)
+{
+       uint32 rid[MAX_SAM_ENTRIES];
+       uint32 status     = 0;
+       int num_rids = q_u->num_sids1;
+
+       SAMR_R_LOOKUP_IDS r_u;
+
+       DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
+
+       if (num_rids > MAX_SAM_ENTRIES)
+       {
+               num_rids = MAX_SAM_ENTRIES;
+               DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
+       }
+
+#if 0
+       int i;
+       SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
+
+       for (i = 0; i < num_rids && status == 0; i++)
+       {
+               struct sam_passwd *sam_pass;
+               fstring user_name;
+
+
+               fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer,
+                                           q_u->uni_user_name[i].uni_str_len));
+
+               /* find the user account */
+               become_root(True);
+               sam_pass = get_smb21pwd_entry(user_name, 0);
+               unbecome_root(True);
+
+               if (sam_pass == NULL)
+               {
+                       status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
+                       rid[i] = 0;
+               }
+               else
+               {
+                       rid[i] = sam_pass->user_rid;
+               }
+       }
+#endif
+
+       num_rids = 1;
+       rid[0] = BUILTIN_ALIAS_RID_USERS;
+
+       make_samr_r_lookup_ids(&r_u, num_rids, rid, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_lookup_ids("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_lookup_ids
+ ********************************************************************/
+static void api_samr_lookup_ids( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_LOOKUP_IDS q_u;
+
+       /* grab the samr 0x10 */
+       samr_io_q_lookup_ids("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_lookup_ids(&q_u, rdata);
+}
+
+/*******************************************************************
+ samr_reply_lookup_names
+ ********************************************************************/
+static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
+                               prs_struct *rdata)
+{
+       uint32 rid[MAX_SAM_ENTRIES];
+       uint32 status     = 0;
+       int i;
+       int num_rids = q_u->num_rids1;
+
+       SAMR_R_LOOKUP_NAMES r_u;
+
+       DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
+
+       if (num_rids > MAX_SAM_ENTRIES)
+       {
+               num_rids = MAX_SAM_ENTRIES;
+               DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
+       }
+
+       SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
+
+       for (i = 0; i < num_rids && status == 0; i++)
+       {
+               fstring name;
+
+               status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
+
+               fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len));
+
+               status = (status != 0x0) ? lookup_user_rid (name, &(rid[i])) : status;
+               status = (status != 0x0) ? lookup_group_rid(name, &(rid[i])) : status;
+               status = (status != 0x0) ? lookup_alias_rid(name, &(rid[i])) : status;
+       }
+
+       make_samr_r_lookup_names(&r_u, num_rids, rid, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_lookup_names("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_lookup_names
+ ********************************************************************/
+static void api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_LOOKUP_NAMES q_u;
+
+       /* grab the samr lookup names */
+       samr_io_q_lookup_names("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_lookup_names(&q_u, rdata);
+}
+
+/*******************************************************************
+ samr_reply_chgpasswd_user
+ ********************************************************************/
+static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_CHGPASSWD_USER r_u;
+       uint32 status = 0x0;
+       fstring user_name;
+       fstring wks;
+
+       fstrcpy(user_name, unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
+       fstrcpy(wks      , unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
+
+       DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
+
+       if (!pass_oem_change(user_name,
+                            q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
+                            q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
+       {
+               status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
+       }
+
+       make_samr_r_chgpasswd_user(&r_u, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_chgpasswd_user("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_samr_chgpasswd_user
+ ********************************************************************/
+static void api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_CHGPASSWD_USER q_u;
+
+       /* unknown 38 command */
+       samr_io_q_chgpasswd_user("", &q_u, data, 0);
+
+       /* construct reply. */
+       samr_reply_chgpasswd_user(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_unknown_38
+ ********************************************************************/
+static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_UNKNOWN_38 r_u;
+
+       DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
+
+       make_samr_r_unknown_38(&r_u);
+
+       /* store the response in the SMB stream */
+       samr_io_r_unknown_38("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_samr_unknown_38
+ ********************************************************************/
+static void api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_UNKNOWN_38 q_u;
+
+       /* unknown 38 command */
+       samr_io_q_unknown_38("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_unknown_38(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_unknown_12
+ ********************************************************************/
+static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
+                               prs_struct *rdata)
+{
+       fstring group_names[MAX_SAM_ENTRIES];
+       uint32  group_attrs[MAX_SAM_ENTRIES];
+       uint32 status     = 0;
+       int num_gids = q_u->num_gids1;
+
+       SAMR_R_UNKNOWN_12 r_u;
+
+       DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
+
+       /* find the policy handle.  open a policy on it. */
+       if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (status == 0x0)
+       {
+               int i;
+               if (num_gids > MAX_SAM_ENTRIES)
+               {
+                       num_gids = MAX_SAM_ENTRIES;
+                       DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
+               }
+
+               for (i = 0; i < num_gids && status == 0; i++)
+               {
+                       fstrcpy(group_names[i], "dummy group");
+                       group_attrs[i] = 0x2;
+               }
+       }
+
+       make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_unknown_12("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_unknown_12
+ ********************************************************************/
+static void api_samr_unknown_12( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_UNKNOWN_12 q_u;
+
+       /* grab the samr lookup names */
+       samr_io_q_unknown_12("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_unknown_12(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_open_user
+ ********************************************************************/
+static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
+                               prs_struct *rdata,
+                               int status)
+{
+       SAMR_R_OPEN_USER r_u;
+       struct sam_passwd *sam_pass;
+       BOOL pol_open = False;
+
+       /* set up the SAMR open_user response */
+       memset((char *)r_u.user_pol.data, '\0', POL_HND_SIZE);
+
+       r_u.status = 0x0;
+
+       /* find the policy handle.  open a policy on it. */
+       if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* get a (unique) handle.  open a policy on it. */
+       if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       become_root(True);
+       sam_pass = getsam21pwrid(q_u->user_rid);
+       unbecome_root(True);
+
+       /* check that the RID exists in our domain. */
+       if (r_u.status == 0x0 && sam_pass == NULL)
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
+       }
+
+       /* associate the RID with the (unique) handle. */
+       if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
+       {
+               /* oh, whoops.  don't know what error message to return, here */
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (r_u.status != 0 && pol_open)
+       {
+               close_lsa_policy_hnd(&(r_u.user_pol));
+       }
+
+       DEBUG(5,("samr_open_user: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_open_user("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_open_user: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_open_user
+ ********************************************************************/
+static void api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_OPEN_USER q_u;
+
+       /* grab the samr unknown 22 */
+       samr_io_q_open_user("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_open_user(&q_u, rdata, 0x0);
+}
+
+
+/*************************************************************************
+ get_user_info_10
+ *************************************************************************/
+static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
+{
+       struct smb_passwd *smb_pass;
+
+       if (!pdb_rid_is_user(user_rid))
+       {
+               DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
+               return False;
+       }
+
+       become_root(True);
+       smb_pass = getsmbpwrid(user_rid);
+       unbecome_root(True);
+
+       if (smb_pass == NULL)
+       {
+               DEBUG(4,("User 0x%x not found\n", user_rid));
+               return False;
+       }
+
+       DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
+
+       make_sam_user_info10(id10, smb_pass->acct_ctrl); 
+
+       return True;
+}
+
+/*************************************************************************
+ get_user_info_21
+ *************************************************************************/
+static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
+{
+       NTTIME dummy_time;
+       struct sam_passwd *sam_pass;
+       LOGON_HRS hrs;
+       int i;
+
+       if (!pdb_rid_is_user(user_rid))
+       {
+               DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
+               return False;
+       }
+
+       become_root(True);
+       sam_pass = getsam21pwrid(user_rid);
+       unbecome_root(True);
+
+       if (sam_pass == NULL)
+       {
+               DEBUG(4,("User 0x%x not found\n", user_rid));
+               return False;
+       }
+
+       DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
+
+       dummy_time.low  = 0xffffffff;
+       dummy_time.high = 0x7fffffff;
+
+       DEBUG(0,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
+
+       /* create a LOGON_HRS structure */
+       hrs.len = sam_pass->hours_len;
+       SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
+       for (i = 0; i < hrs.len; i++)
+       {
+               hrs.hours[i] = sam_pass->hours[i];
+       }
+
+       make_sam_user_info21(id21,
+
+                          &dummy_time, /* logon_time */
+                          &dummy_time, /* logoff_time */
+                          &dummy_time, /* kickoff_time */
+                          &dummy_time, /* pass_last_set_time */
+                          &dummy_time, /* pass_can_change_time */
+                          &dummy_time, /* pass_must_change_time */
+
+                          sam_pass->smb_name, /* user_name */
+                          sam_pass->full_name, /* full_name */
+                          sam_pass->home_dir, /* home_dir */
+                          sam_pass->dir_drive, /* dir_drive */
+                          sam_pass->logon_script, /* logon_script */
+                          sam_pass->profile_path, /* profile_path */
+                          sam_pass->acct_desc, /* description */
+                          sam_pass->workstations, /* workstations user can log in from */
+                          sam_pass->unknown_str, /* don't know, yet */
+                          sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
+
+                          sam_pass->user_rid, /* RID user_id */
+                          sam_pass->group_rid, /* RID group_id */
+                      sam_pass->acct_ctrl,
+
+                  sam_pass->unknown_3, /* unknown_3 */
+                      sam_pass->logon_divs, /* divisions per week */
+                          &hrs, /* logon hours */
+                      sam_pass->unknown_5,
+                      sam_pass->unknown_6);
+
+       return True;
+}
+
+/*******************************************************************
+ samr_reply_query_userinfo
+ ********************************************************************/
+static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_QUERY_USERINFO r_u;
+#if 0
+       SAM_USER_INFO_11 id11;
+#endif
+       SAM_USER_INFO_10 id10;
+       SAM_USER_INFO_21 id21;
+       void *info = NULL;
+
+       uint32 status = 0x0;
+       uint32 rid = 0x0;
+
+       DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
+
+       /* search for the handle */
+       if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               status = NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* find the user's rid */
+       if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
+       {
+               status = NT_STATUS_OBJECT_TYPE_MISMATCH;
+       }
+
+       DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
+
+       /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
+       if (status == 0x0)
+       {
+               switch (q_u->switch_value)
+               {
+                       case 0x10:
+                       {
+                               info = (void*)&id10;
+                               status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
+                               break;
+                       }
+#if 0
+/* whoops - got this wrong.  i think.  or don't understand what's happening. */
+                       case 0x11:
+                       {
+                               NTTIME expire;
+                               info = (void*)&id11;
+                               
+                               expire.low  = 0xffffffff;
+                               expire.high = 0x7fffffff;
+
+                               make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
+
+                               break;
+                       }
+#endif
+                       case 21:
+                       {
+                               info = (void*)&id21;
+                               status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
+                               break;
+                       }
+
+                       default:
+                       {
+                               status = NT_STATUS_INVALID_INFO_CLASS;
+
+                               break;
+                       }
+               }
+       }
+
+       make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_query_userinfo("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_query_userinfo
+ ********************************************************************/
+static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_QUERY_USERINFO q_u;
+
+       /* grab the samr unknown 24 */
+       samr_io_q_query_userinfo("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_query_userinfo(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_query_usergroups
+ ********************************************************************/
+static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_QUERY_USERGROUPS r_u;
+       uint32 status = 0x0;
+
+       struct sam_passwd *sam_pass;
+       DOM_GID *gids = NULL;
+       int num_groups = 0;
+       uint32 rid;
+
+       DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
+
+       /* find the policy handle.  open a policy on it. */
+       if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       {
+               status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* find the user's rid */
+       if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
+       {
+               status = NT_STATUS_OBJECT_TYPE_MISMATCH;
+       }
+
+       if (status == 0x0)
+       {
+               become_root(True);
+               sam_pass = getsam21pwrid(rid);
+               unbecome_root(True);
+
+               if (sam_pass == NULL)
+               {
+                       status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
+               }
+       }
+
+       if (status == 0x0)
+       {
+               pstring groups;
+               get_domain_user_groups(groups, sam_pass->smb_name);
+                gids = NULL;
+               num_groups = make_dom_gids(groups, &gids);
+       }
+
+       /* construct the response.  lkclXXXX: gids are not copied! */
+       make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_query_usergroups("", &r_u, rdata, 0);
+
+       if (gids)
+       {
+               free((char *)gids);
+       }
+
+       DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_query_usergroups
+ ********************************************************************/
+static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_QUERY_USERGROUPS q_u;
+       /* grab the samr unknown 32 */
+       samr_io_q_query_usergroups("", &q_u, data, 0);
+
+       /* construct reply. */
+       samr_reply_query_usergroups(&q_u, rdata);
+}
+
+
+/*******************************************************************
+ samr_reply_query_dom_info
+ ********************************************************************/
+static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_QUERY_DOMAIN_INFO r_u;
+       SAM_UNK_CTR ctr;
+       uint16 switch_value = 0x0;
+       uint32 status = 0x0;
+
+       ZERO_STRUCT(r_u);
+       ZERO_STRUCT(ctr);
+
+       r_u.ctr = &ctr;
+
+       DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
+
+       /* find the policy handle.  open a policy on it. */
+       if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+               DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
+       }
+
+       if (status == 0x0)
+       {
+               switch (q_u->switch_value)
+               {
+                       case 0x02:
+                       {
+                               switch_value = 0x2;
+                               make_unk_info2(&ctr.info.inf2, global_myworkgroup, global_myname);
+
+                               break;
+                       }
+                       default:
+                       {
+                               status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+                               break;
+                       }
+               }
+       }
+
+       make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
+
+       /* store the response in the SMB stream */
+       samr_io_r_query_dom_info("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_query_dom_info
+ ********************************************************************/
+static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_QUERY_DOMAIN_INFO q_e;
+
+       /* grab the samr unknown 8 command */
+       samr_io_q_query_dom_info("", &q_e, data, 0);
+
+       /* construct reply. */
+       samr_reply_query_dom_info(&q_e, rdata);
+}
+
+
+
+/*******************************************************************
+ samr_reply_unknown_32
+ ********************************************************************/
+static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
+                               prs_struct *rdata,
+                               int status)
+{
+       int i;
+       SAMR_R_UNKNOWN_32 r_u;
+
+       /* set up the SAMR unknown_32 response */
+       memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
+       if (status == 0)
+       {
+               for (i = 4; i < POL_HND_SIZE; i++)
+               {
+                       r_u.pol.data[i] = i+1;
+               }
+       }
+
+       make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
+       r_u.status    = status;
+
+       DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_unknown_32("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_unknown_32
+ ********************************************************************/
+static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       uint32 status = 0;
+       struct sam_passwd *sam_pass;
+       fstring mach_acct;
+
+       SAMR_Q_UNKNOWN_32 q_u;
+
+       /* grab the samr unknown 32 */
+       samr_io_q_unknown_32("", &q_u, data, 0);
+
+       /* find the machine account: tell the caller if it exists.
+          lkclXXXX i have *no* idea if this is a problem or not
+          or even if you are supposed to construct a different
+          reply if the account already exists...
+        */
+
+       fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer,
+                                   q_u.uni_mach_acct.uni_str_len));
+
+       become_root(True);
+       sam_pass = getsam21pwnam(mach_acct);
+       unbecome_root(True);
+
+       if (sam_pass != NULL)
+       {
+               /* machine account exists: say so */
+               status = 0xC0000000 | NT_STATUS_USER_EXISTS;
+       }
+       else
+       {
+               /* this could cause trouble... */
+               DEBUG(0,("trouble!\n"));
+               status = 0;
+       }
+
+       /* construct reply. */
+       samr_reply_unknown_32(&q_u, rdata, status);
+}
+
+
+/*******************************************************************
+ samr_reply_connect_anon
+ ********************************************************************/
+static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_CONNECT_ANON r_u;
+       BOOL pol_open = False;
+
+       /* set up the SAMR connect_anon response */
+
+       r_u.status = 0x0;
+       /* get a (unique) handle.  open a policy on it. */
+       if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       /* associate the domain SID with the (unique) handle. */
+       if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
+       {
+               /* oh, whoops.  don't know what error message to return, here */
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (r_u.status != 0 && pol_open)
+       {
+               close_lsa_policy_hnd(&(r_u.connect_pol));
+       }
+
+       DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_connect_anon("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_connect_anon
+ ********************************************************************/
+static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_CONNECT_ANON q_u;
+
+       /* grab the samr open policy */
+       samr_io_q_connect_anon("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_connect_anon(&q_u, rdata);
+}
+
+/*******************************************************************
+ samr_reply_connect
+ ********************************************************************/
+static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_CONNECT r_u;
+       BOOL pol_open = False;
+
+       /* set up the SAMR connect response */
+
+       r_u.status = 0x0;
+       /* get a (unique) handle.  open a policy on it. */
+       if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       /* associate the domain SID with the (unique) handle. */
+       if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
+       {
+               /* oh, whoops.  don't know what error message to return, here */
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (r_u.status != 0 && pol_open)
+       {
+               close_lsa_policy_hnd(&(r_u.connect_pol));
+       }
+
+       DEBUG(5,("samr_connect: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_connect("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_connect: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_connect
+ ********************************************************************/
+static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_CONNECT q_u;
+
+       /* grab the samr open policy */
+       samr_io_q_connect("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_connect(&q_u, rdata);
+}
+
+/*******************************************************************
+ samr_reply_open_alias
+ ********************************************************************/
+static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_OPEN_ALIAS r_u;
+       BOOL pol_open = False;
+
+       /* set up the SAMR open_alias response */
+
+       r_u.status = 0x0;
+       /* get a (unique) handle.  open a policy on it. */
+       if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       /* associate a RID with the (unique) handle. */
+       if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
+       {
+               /* oh, whoops.  don't know what error message to return, here */
+               r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (r_u.status != 0 && pol_open)
+       {
+               close_lsa_policy_hnd(&(r_u.pol));
+       }
+
+       DEBUG(5,("samr_open_alias: %d\n", __LINE__));
+
+       /* store the response in the SMB stream */
+       samr_io_r_open_alias("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_open_alias: %d\n", __LINE__));
+
+}
+
+/*******************************************************************
+ api_samr_open_alias
+ ********************************************************************/
+static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
+                                
+{
+       SAMR_Q_OPEN_ALIAS q_u;
+
+       /* grab the samr open policy */
+       samr_io_q_open_alias("", &q_u, data, 0);
+
+       /* construct reply.  always indicate success */
+       samr_reply_open_alias(&q_u, rdata);
+}
+
+/*******************************************************************
+ array of \PIPE\samr operations
+ ********************************************************************/
+static struct api_struct api_samr_cmds [] =
+{
+       { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
+       { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
+       { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
+       { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
+       { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
+       { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
+       { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
+       { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
+       { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
+       { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
+       { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info        },
+       { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
+       { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
+       { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
+       { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
+       { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
+       { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
+       { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
+       { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
+       { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
+       { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
+       { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
+       { NULL                    , 0                     , NULL                      }
+};
+
+/*******************************************************************
+ receives a samr pipe and responds.
+ ********************************************************************/
+BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
+{
+    return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
+}
+
index d482e46b5886d2eb663cdf94a5410e9afe4f5fe2..c7aeee9b117ef25eb85481aa5a70ee1ce727a02b 100644 (file)
@@ -274,6 +274,579 @@ static void srv_reply_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n,
        DEBUG(5,("srv_net_share_enum: %d\n", __LINE__));
 }
 
+/*******************************************************************
+ fill in a sess info level 1 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_sess_0_info(SESS_INFO_0    *se0, SESS_INFO_0_STR *str0,
+                               char *name)
+{
+       make_srv_sess_info0    (se0 , name);
+       make_srv_sess_info0_str(str0, name);
+}
+
+/*******************************************************************
+ fill in a sess info level 0 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *stot)
+{
+       uint32 num_entries = 0;
+       (*stot) = 1;
+
+       if (ss0 == NULL)
+       {
+               (*snum) = 0;
+               return;
+       }
+
+       DEBUG(5,("make_srv_sess_0_ss0\n"));
+
+       if (snum)
+       {
+               for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++)
+               {
+                       make_srv_sess_0_info(&(ss0->info_0    [num_entries]),
+                                                                &(ss0->info_0_str[num_entries]), "MACHINE");
+
+                       /* move on to creating next session */
+                       /* move on to creating next sess */
+                       num_entries++;
+               }
+
+               ss0->num_entries_read  = num_entries;
+               ss0->ptr_sess_info     = num_entries > 0 ? 1 : 0;
+               ss0->num_entries_read2 = num_entries;
+               
+               if ((*snum) >= (*stot))
+               {
+                       (*snum) = 0;
+               }
+       }
+       else
+       {
+               ss0->num_entries_read = 0;
+               ss0->ptr_sess_info = 0;
+               ss0->num_entries_read2 = 0;
+       }
+}
+
+/*******************************************************************
+ fill in a sess info level 1 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_sess_1_info(SESS_INFO_1    *se1, SESS_INFO_1_STR *str1,
+                               char *name, char *user,
+                               uint32 num_opens,
+                               uint32 open_time, uint32 idle_time,
+                               uint32 usr_flgs)
+{
+       make_srv_sess_info1    (se1 , name, user, num_opens, open_time, idle_time, usr_flgs);
+       make_srv_sess_info1_str(str1, name, user);
+}
+
+/*******************************************************************
+ fill in a sess info level 1 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *stot)
+{
+       uint32 num_entries = 0;
+       (*stot) = 1;
+
+       if (ss1 == NULL)
+       {
+               (*snum) = 0;
+               return;
+       }
+
+       DEBUG(5,("make_srv_sess_1_ss1\n"));
+
+       if (snum)
+       {
+               for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++)
+               {
+                       make_srv_sess_1_info(&(ss1->info_1    [num_entries]),
+                                                                &(ss1->info_1_str[num_entries]),
+                                            "MACHINE", "dummy_user", 1, 10, 5, 0);
+
+                       /* move on to creating next session */
+                       /* move on to creating next sess */
+                       num_entries++;
+               }
+
+               ss1->num_entries_read  = num_entries;
+               ss1->ptr_sess_info     = num_entries > 0 ? 1 : 0;
+               ss1->num_entries_read2 = num_entries;
+               
+               if ((*snum) >= (*stot))
+               {
+                       (*snum) = 0;
+               }
+       }
+       else
+       {
+               ss1->num_entries_read = 0;
+               ss1->ptr_sess_info = 0;
+               ss1->num_entries_read2 = 0;
+               
+               (*stot) = 0;
+       }
+}
+
+/*******************************************************************
+ makes a SRV_R_NET_SESS_ENUM structure.
+********************************************************************/
+static uint32 make_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr,
+                               int switch_value, uint32 *resume_hnd, uint32 *total_entries)
+{
+       uint32 status = 0x0;
+       DEBUG(5,("make_srv_sess_info_ctr: %d\n", __LINE__));
+
+       ctr->switch_value = switch_value;
+
+       switch (switch_value)
+       {
+               case 0:
+               {
+                       make_srv_sess_info_0(&(ctr->sess.info0), resume_hnd, total_entries);
+                       ctr->ptr_sess_ctr = 1;
+                       break;
+               }
+               case 1:
+               {
+                       make_srv_sess_info_1(&(ctr->sess.info1), resume_hnd, total_entries);
+                       ctr->ptr_sess_ctr = 1;
+                       break;
+               }
+               default:
+               {
+                       DEBUG(5,("make_srv_sess_info_ctr: unsupported switch value %d\n",
+                                 switch_value));
+                       (*resume_hnd) = 0;
+                       (*total_entries) = 0;
+                       ctr->ptr_sess_ctr = 0;
+                       status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+                       break;
+               }
+       }
+
+       return status;
+}
+
+/*******************************************************************
+ makes a SRV_R_NET_SESS_ENUM structure.
+********************************************************************/
+static void make_srv_r_net_sess_enum(SRV_R_NET_SESS_ENUM *r_n,
+                               uint32 resume_hnd, int sess_level, int switch_value)  
+{
+       DEBUG(5,("make_srv_r_net_sess_enum: %d\n", __LINE__));
+
+       r_n->sess_level  = sess_level;
+       if (sess_level == -1)
+       {
+               r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+       }
+       else
+       {
+               r_n->status = make_srv_sess_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries);
+       }
+       if (r_n->status != 0x0)
+       {
+               resume_hnd = 0;
+       }
+       make_enum_hnd(&(r_n->enum_hnd), resume_hnd);
+}
+
+/*******************************************************************
+net sess enum
+********************************************************************/
+static void srv_reply_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n,
+                               prs_struct *rdata)
+{
+       SRV_R_NET_SESS_ENUM r_n;
+       SRV_SESS_INFO_CTR ctr;
+
+       r_n.ctr = &ctr;
+
+       DEBUG(5,("srv_net_sess_enum: %d\n", __LINE__));
+
+       /* set up the */
+       make_srv_r_net_sess_enum(&r_n,
+                               get_enum_hnd(&q_n->enum_hnd),
+                               q_n->sess_level,
+                               q_n->ctr->switch_value);
+
+       /* store the response in the SMB stream */
+       srv_io_r_net_sess_enum("", &r_n, rdata, 0);
+
+       DEBUG(5,("srv_net_sess_enum: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ fill in a conn info level 0 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *stot)
+{
+       uint32 num_entries = 0;
+       (*stot) = 1;
+
+       if (ss0 == NULL)
+       {
+               (*snum) = 0;
+               return;
+       }
+
+       DEBUG(5,("make_srv_conn_0_ss0\n"));
+
+       if (snum)
+       {
+               for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++)
+               {
+                       make_srv_conn_info0(&(ss0->info_0    [num_entries]), (*stot));
+
+                       /* move on to creating next connection */
+                       /* move on to creating next conn */
+                       num_entries++;
+               }
+
+               ss0->num_entries_read  = num_entries;
+               ss0->ptr_conn_info     = num_entries > 0 ? 1 : 0;
+               ss0->num_entries_read2 = num_entries;
+               
+               
+
+               if ((*snum) >= (*stot))
+               {
+                       (*snum) = 0;
+               }
+       }
+       else
+       {
+               ss0->num_entries_read = 0;
+               ss0->ptr_conn_info = 0;
+               ss0->num_entries_read2 = 0;
+
+               (*stot) = 0;
+       }
+}
+
+/*******************************************************************
+ fill in a conn info level 1 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_conn_1_info(CONN_INFO_1    *se1, CONN_INFO_1_STR *str1,
+                               uint32 id, uint32 type,
+                               uint32 num_opens, uint32 num_users, uint32 open_time,
+                               char *usr_name, char *net_name)
+{
+       make_srv_conn_info1    (se1 , id, type, num_opens, num_users, open_time, usr_name, net_name);
+       make_srv_conn_info1_str(str1, usr_name, net_name);
+}
+
+/*******************************************************************
+ fill in a conn info level 1 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *stot)
+{
+       uint32 num_entries = 0;
+       (*stot) = 1;
+
+       if (ss1 == NULL)
+       {
+               (*snum) = 0;
+               return;
+       }
+
+       DEBUG(5,("make_srv_conn_1_ss1\n"));
+
+       if (snum)
+       {
+               for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++)
+               {
+                       make_srv_conn_1_info(&(ss1->info_1    [num_entries]),
+                                                                &(ss1->info_1_str[num_entries]),
+                                            (*stot), 0x3, 1, 1, 3,"dummy_user", "IPC$");
+
+                       /* move on to creating next connection */
+                       /* move on to creating next conn */
+                       num_entries++;
+               }
+
+               ss1->num_entries_read  = num_entries;
+               ss1->ptr_conn_info     = num_entries > 0 ? 1 : 0;
+               ss1->num_entries_read2 = num_entries;
+               
+
+               if ((*snum) >= (*stot))
+               {
+                       (*snum) = 0;
+               }
+       }
+       else
+       {
+               ss1->num_entries_read = 0;
+               ss1->ptr_conn_info = 0;
+               ss1->num_entries_read2 = 0;
+               
+               (*stot) = 0;
+       }
+}
+
+/*******************************************************************
+ makes a SRV_R_NET_CONN_ENUM structure.
+********************************************************************/
+static uint32 make_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr,
+                               int switch_value, uint32 *resume_hnd, uint32 *total_entries)
+{
+       uint32 status = 0x0;
+       DEBUG(5,("make_srv_conn_info_ctr: %d\n", __LINE__));
+
+       ctr->switch_value = switch_value;
+
+       switch (switch_value)
+       {
+               case 0:
+               {
+                       make_srv_conn_info_0(&(ctr->conn.info0), resume_hnd, total_entries);
+                       ctr->ptr_conn_ctr = 1;
+                       break;
+               }
+               case 1:
+               {
+                       make_srv_conn_info_1(&(ctr->conn.info1), resume_hnd, total_entries);
+                       ctr->ptr_conn_ctr = 1;
+                       break;
+               }
+               default:
+               {
+                       DEBUG(5,("make_srv_conn_info_ctr: unsupported switch value %d\n",
+                                 switch_value));
+                       (*resume_hnd = 0);
+                       (*total_entries) = 0;
+                       ctr->ptr_conn_ctr = 0;
+                       status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+                       break;
+               }
+       }
+
+       return status;
+}
+
+/*******************************************************************
+ makes a SRV_R_NET_CONN_ENUM structure.
+********************************************************************/
+static void make_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
+                               uint32 resume_hnd, int conn_level, int switch_value)  
+{
+       DEBUG(5,("make_srv_r_net_conn_enum: %d\n", __LINE__));
+
+       r_n->conn_level  = conn_level;
+       if (conn_level == -1)
+       {
+               r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+       }
+       else
+       {
+               r_n->status = make_srv_conn_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries);
+       }
+       if (r_n->status != 0x0)
+       {
+               resume_hnd = 0;
+       }
+       make_enum_hnd(&(r_n->enum_hnd), resume_hnd);
+}
+
+/*******************************************************************
+net conn enum
+********************************************************************/
+static void srv_reply_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n,
+                               prs_struct *rdata)
+{
+       SRV_R_NET_CONN_ENUM r_n;
+       SRV_CONN_INFO_CTR ctr;
+
+       r_n.ctr = &ctr;
+
+       DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
+
+       /* set up the */
+       make_srv_r_net_conn_enum(&r_n,
+                               get_enum_hnd(&q_n->enum_hnd),
+                               q_n->conn_level,
+                               q_n->ctr->switch_value);
+
+       /* store the response in the SMB stream */
+       srv_io_r_net_conn_enum("", &r_n, rdata, 0);
+
+       DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ fill in a file info level 3 structure.
+ ********************************************************************/
+static void make_srv_file_3_info(FILE_INFO_3     *fl3, FILE_INFO_3_STR *str3,
+                               uint32 fnum, uint32 perms, uint32 num_locks,
+                               char *path_name, char *user_name)
+{
+       make_srv_file_info3    (fl3 , fnum, perms, num_locks, path_name, user_name);
+       make_srv_file_info3_str(str3, path_name, user_name);
+}
+
+/*******************************************************************
+ fill in a file info level 3 structure.
+
+ this function breaks the rule that i'd like to be in place, namely
+ it doesn't receive its data as arguments: it has to call lp_xxxx()
+ functions itself.  yuck.
+
+ ********************************************************************/
+static void make_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *ftot)
+{
+       uint32 num_entries = 0;
+       (*ftot) = 1;
+
+       if (fl3 == NULL)
+       {
+               (*fnum) = 0;
+               return;
+       }
+
+       DEBUG(5,("make_srv_file_3_fl3\n"));
+
+       for (; (*fnum) < (*ftot) && num_entries < MAX_FILE_ENTRIES; (*fnum)++)
+       {
+               make_srv_file_3_info(&(fl3->info_3    [num_entries]),
+                                        &(fl3->info_3_str[num_entries]),
+                                    (*fnum), 0x35, 0, "\\PIPE\\samr", "dummy user");
+
+               /* move on to creating next file */
+               num_entries++;
+       }
+
+       fl3->num_entries_read  = num_entries;
+       fl3->ptr_file_info     = num_entries > 0 ? 1 : 0;
+       fl3->num_entries_read2 = num_entries;
+       
+       if ((*fnum) >= (*ftot))
+       {
+               (*fnum) = 0;
+       }
+}
+
+/*******************************************************************
+ makes a SRV_R_NET_FILE_ENUM structure.
+********************************************************************/
+static uint32 make_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr,
+                               int switch_value, uint32 *resume_hnd, uint32 *total_entries)  
+{
+       uint32 status = 0x0;
+       DEBUG(5,("make_srv_file_info_ctr: %d\n", __LINE__));
+
+       ctr->switch_value = switch_value;
+
+       switch (switch_value)
+       {
+               case 3:
+               {
+                       make_srv_file_info_3(&(ctr->file.info3), resume_hnd, total_entries);
+                       ctr->ptr_file_ctr = 1;
+                       break;
+               }
+               default:
+               {
+                       DEBUG(5,("make_srv_file_info_ctr: unsupported switch value %d\n",
+                                 switch_value));
+                       (*resume_hnd = 0);
+                       (*total_entries) = 0;
+                       ctr->ptr_file_ctr = 0;
+                       status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+                       break;
+               }
+       }
+
+       return status;
+}
+
+/*******************************************************************
+ makes a SRV_R_NET_FILE_ENUM structure.
+********************************************************************/
+static void make_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n,
+                               uint32 resume_hnd, int file_level, int switch_value)  
+{
+       DEBUG(5,("make_srv_r_net_file_enum: %d\n", __LINE__));
+
+       r_n->file_level  = file_level;
+       if (file_level == 0)
+       {
+               r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
+       }
+       else
+       {
+               r_n->status = make_srv_file_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
+       }
+       if (r_n->status != 0x0)
+       {
+               resume_hnd = 0;
+       }
+       make_enum_hnd(&(r_n->enum_hnd), resume_hnd);
+}
+
+/*******************************************************************
+net file enum
+********************************************************************/
+static void srv_reply_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
+                               prs_struct *rdata)
+{
+       SRV_R_NET_FILE_ENUM r_n;
+       SRV_FILE_INFO_CTR ctr;
+
+       r_n.ctr = &ctr;
+
+       DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
+
+       /* set up the */
+       make_srv_r_net_file_enum(&r_n,
+                               get_enum_hnd(&q_n->enum_hnd),
+                               q_n->file_level,
+                               q_n->ctr->switch_value);
+
+       /* store the response in the SMB stream */
+       srv_io_r_net_file_enum("", &r_n, rdata, 0);
+
+       DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
+}
+
 /*******************************************************************
 net server get info
 ********************************************************************/
@@ -344,6 +917,59 @@ static void api_srv_net_srv_get_info( uint16 vuid, prs_struct *data,
 }
 
 
+/*******************************************************************
+********************************************************************/
+static void api_srv_net_file_enum( uint16 vuid, prs_struct *data,
+                                    prs_struct *rdata )
+{
+       SRV_Q_NET_FILE_ENUM q_n;
+       SRV_FILE_INFO_CTR ctr;
+
+       q_n.ctr = &ctr;
+
+       /* grab the net file enum */
+       srv_io_q_net_file_enum("", &q_n, data, 0);
+
+       /* construct reply.  always indicate success */
+       srv_reply_net_file_enum(&q_n, rdata);
+}
+
+
+/*******************************************************************
+********************************************************************/
+static void api_srv_net_conn_enum( uint16 vuid, prs_struct *data,
+                                    prs_struct *rdata )
+{
+       SRV_Q_NET_CONN_ENUM q_n;
+       SRV_CONN_INFO_CTR ctr;
+
+       q_n.ctr = &ctr;
+
+       /* grab the net server get enum */
+       srv_io_q_net_conn_enum("", &q_n, data, 0);
+
+       /* construct reply.  always indicate success */
+       srv_reply_net_conn_enum(&q_n, rdata);
+}
+
+
+/*******************************************************************
+********************************************************************/
+static void api_srv_net_sess_enum( uint16 vuid, prs_struct *data,
+                                    prs_struct *rdata )
+{
+       SRV_Q_NET_SESS_ENUM q_n;
+       SRV_SESS_INFO_CTR ctr;
+
+       q_n.ctr = &ctr;
+
+       /* grab the net server get enum */
+       srv_io_q_net_sess_enum("", &q_n, data, 0);
+
+       /* construct reply.  always indicate success */
+       srv_reply_net_sess_enum(&q_n, rdata);
+}
+
 
 /*******************************************************************
 ********************************************************************/
@@ -421,7 +1047,10 @@ static void api_srv_net_remote_tod( uint16 vuid, prs_struct *data,
 ********************************************************************/
 struct api_struct api_srv_cmds[] =
 {
+       { "SRV_NETCONNENUM"     , SRV_NETCONNENUM     , api_srv_net_conn_enum    },
+       { "SRV_NETSESSENUM"     , SRV_NETSESSENUM     , api_srv_net_sess_enum    },
        { "SRV_NETSHAREENUM"    , SRV_NETSHAREENUM    , api_srv_net_share_enum   },
+       { "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   },
        { NULL                  , 0                   , NULL                     }
index 375fada6a4dd8f9d71f2b334fe91509361d72528..a23e7a650b7db4532a2294faaebfba9e2210d1b0 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+#define DEBUG_TESTING
+
+extern struct cli_state *smb_cli;
+extern int smb_tidx;
+
+extern FILE* out_hnd;
+
+
+/****************************************************************************
+nt lsa query
+****************************************************************************/
+void cmd_lsa_query_info(struct client_info *info)
+{
+       fstring srv_name;
+
+       BOOL res = True;
+
+       fstrcpy(info->dom.level3_dom, "");
+       fstrcpy(info->dom.level5_dom, "");
+       ZERO_STRUCT(info->dom.level3_sid);
+       ZERO_STRUCT(info->dom.level5_sid);
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->myhostname);
+       strupper(srv_name);
+
+       DEBUG(4,("cmd_lsa_query_info: server:%s\n", srv_name));
+
+       DEBUG(5, ("cmd_lsa_query_info: smb_cli->fd:%d\n", smb_cli->fd));
+
+       /* open LSARPC session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_LSARPC) : False;
+
+       /* lookup domain controller; receive a policy handle */
+       res = res ? do_lsa_open_policy(smb_cli,
+                               srv_name,
+                               &info->dom.lsa_info_pol, False) : False;
+
+       /* send client info query, level 3.  receive domain name and sid */
+       res = res ? do_lsa_query_info_pol(smb_cli, 
+                                         &info->dom.lsa_info_pol, 0x03,
+                                         info->dom.level3_dom,
+                                         &info->dom.level3_sid) : False;
+
+       /* send client info query, level 5.  receive domain name and sid */
+       res = res ? do_lsa_query_info_pol(smb_cli,
+                               &info->dom.lsa_info_pol, 0x05,
+                               info->dom.level5_dom,
+                               &info->dom.level5_sid) : False;
+
+       res = res ? do_lsa_close(smb_cli, &info->dom.lsa_info_pol) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               BOOL domain_something = False;
+               fstring sid;
+               DEBUG(5,("cmd_lsa_query_info: query succeeded\n"));
+
+               fprintf(out_hnd, "LSA Query Info Policy\n");
+
+               if (info->dom.level3_dom[0] != 0)
+               {
+                       sid_to_string(sid, &info->dom.level3_sid);
+                       fprintf(out_hnd, "Domain Member     - Domain: %s SID: %s\n",
+                               info->dom.level3_dom, sid);
+                       domain_something = True;
+               }
+               if (info->dom.level5_dom[0] != 0)
+               {
+                       sid_to_string(sid, &info->dom.level5_sid);
+                       fprintf(out_hnd, "Domain Controller - Domain: %s SID: %s\n",
+                               info->dom.level5_dom, sid);
+                       domain_something = True;
+               }
+               if (!domain_something)
+               {
+                       fprintf(out_hnd, "%s is not a Domain Member or Controller\n",
+                           info->dest_host);
+               }
+       }
+       else
+       {
+               DEBUG(5,("cmd_lsa_query_info: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt lsa query
+****************************************************************************/
+void cmd_lsa_lookup_sids(struct client_info *info)
+{
+       fstring temp;
+       int i;
+       pstring sid_name;
+       fstring srv_name;
+       DOM_SID sid[10];
+       DOM_SID *sids[10];
+       int num_sids = 0;
+       char **names = NULL;
+       int num_names = 0;
+
+       BOOL res = True;
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->myhostname);
+       strupper(srv_name);
+
+       DEBUG(4,("cmd_lsa_lookup_sids: server: %s\n", srv_name));
+
+       while (num_sids < 10 && next_token(NULL, temp, NULL, sizeof(temp)))
+       {
+               if (strnequal("S-", temp, 2))
+               {
+                       fstrcpy(sid_name, temp);
+               }
+               else
+               {
+                       sid_to_string(sid_name, &info->dom.level5_sid);
+
+                       if (sid_name[0] == 0)
+                       {
+                               fprintf(out_hnd, "please use lsaquery first or specify a complete SID\n");
+                               return;
+                       }
+                               
+                       fstrcat(sid_name, "-");
+                       fstrcat(sid_name, temp);
+               }
+               make_dom_sid(&sid[num_sids], sid_name);
+               sids[num_sids] = &sid[num_sids];
+               num_sids++;
+       }
+
+       if (num_sids == 0)
+       {
+               fprintf(out_hnd, "lookupsid RID or SID\n");
+               return;
+       }
+
+       /* open LSARPC session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_LSARPC) : False;
+
+       /* lookup domain controller; receive a policy handle */
+       res = res ? do_lsa_open_policy(smb_cli,
+                               srv_name,
+                               &info->dom.lsa_info_pol, True) : False;
+
+       /* send lsa lookup sids call */
+       res = res ? do_lsa_lookup_sids(smb_cli, 
+                                      &info->dom.lsa_info_pol,
+                                      num_sids, sids,
+                                      &names, &num_names) : False;
+
+       res = res ? do_lsa_close(smb_cli, &info->dom.lsa_info_pol) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_lsa_lookup_sids: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_lsa_lookup_sids: query failed\n"));
+       }
+       if (names != NULL)
+       {
+               fprintf(out_hnd,"Lookup SIDS:\n");
+               for (i = 0; i < num_names; i++)
+               {
+                       sid_to_string(temp, sids[i]);
+                       fprintf(out_hnd, "SID: %s -> %s\n", temp, names[i]);
+                       if (names[i] != NULL)
+                       {
+                               free(names[i]);
+                       }
+               }
+               free(names);
+       }
+}
+
index 24f59b4f640c1947b2d4df87a7fe52c0bef7e50f..2c8514b43e8def6fbf45b513d35e87033803ab67 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+#define DEBUG_TESTING
+
+extern struct cli_state *smb_cli;
+
+extern FILE* out_hnd;
+
+
+/****************************************************************************
+experimental nt login.
+****************************************************************************/
+void cmd_netlogon_login_test(struct client_info *info)
+{
+       extern BOOL global_machine_password_needs_changing;
+
+       fstring nt_user_name;
+       fstring password;
+       BOOL res = True;
+       char *nt_password;
+       unsigned char trust_passwd[16];
+
+#if 0
+       /* machine account passwords */
+       pstring new_mach_pwd;
+
+       /* initialisation */
+       new_mach_pwd[0] = 0;
+#endif
+
+       if (!next_token(NULL, nt_user_name, NULL, sizeof(nt_user_name)))
+       {
+               fstrcpy(nt_user_name, smb_cli->user_name);
+               if (nt_user_name[0] == 0)
+               {
+                       fprintf(out_hnd,"ntlogin: must specify username with anonymous connection\n");
+                       return;
+               }
+       }
+
+       if (next_token(NULL, password, NULL, sizeof(password)))
+       {
+               nt_password = password;
+       }
+       else
+       {
+               nt_password = getpass("Enter NT Login password:");
+       }
+
+       DEBUG(5,("do_nt_login_test: username %s\n", nt_user_name));
+
+       res = res ? trust_get_passwd(trust_passwd, smb_cli->domain, info->myhostname) : False;
+
+#if 0
+       /* check whether the user wants to change their machine password */
+       res = res ? trust_account_check(info->dest_ip, info->dest_host,
+                                       info->myhostname, smb_cli->domain,
+                                       info->mach_acct, new_mach_pwd) : False;
+#endif
+       /* open NETLOGON session.  negotiate credentials */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_NETLOGON) : False;
+
+       res = res ? cli_nt_setup_creds(smb_cli, trust_passwd) : False;
+
+       /* change the machine password? */
+       if (global_machine_password_needs_changing)
+       {
+               unsigned char new_trust_passwd[16];
+               generate_random_buffer(new_trust_passwd, 16, True);
+               res = res ? cli_nt_srv_pwset(smb_cli, new_trust_passwd) : False;
+
+               if (res)
+               {
+                       global_machine_password_needs_changing = !set_trust_account_password(new_trust_passwd);
+               }
+
+               memset(new_trust_passwd, 0, 16);
+       }
+
+       memset(trust_passwd, 0, 16);
+
+       /* do an NT login */
+       res = res ? cli_nt_login_interactive(smb_cli,
+                        smb_cli->domain, nt_user_name,
+                        getuid(), nt_password,
+                        &info->dom.ctr, &info->dom.user_info3) : False;
+
+       /*** clear out the password ***/
+       memset(password, 0, sizeof(password));
+
+       /* ok!  you're logged in!  do anything you like, then... */
+
+       /* do an NT logout */
+       res = res ? cli_nt_logoff(smb_cli, &info->dom.ctr) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       fprintf(out_hnd,"cmd_nt_login: login (%s) test succeeded: %s\n",
+               nt_user_name, BOOLSTR(res));
+}
+
index 24f59b4f640c1947b2d4df87a7fe52c0bef7e50f..79ee7b1563f2573319fade6911b5f4269965b998 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+extern struct cli_state *smb_cli;
+extern int smb_tidx;
+
+extern FILE* out_hnd;
+
+/*
+ * keys.  of the form:
+ * ----
+ *
+ * [HKLM]|[HKU]\[parent_keyname_components]\[subkey]|[value]
+ *
+ * reg_getsubkey() splits this down into:
+ * [HKLM]|[HKU]\[parent_keyname_components] and [subkey]|[value]
+ *
+ * do_reg_connect() splits the left side down further into:
+ * [HKLM]|[HKU] and [parent_keyname_components].
+ *
+ * HKLM is short for HKEY_LOCAL_MACHINE
+ * HKU  is short for HKEY_USERS
+ *
+ * oh, and HKEY stands for "Hive Key".
+ *
+ */
+
+/****************************************************************************
+nt registry enum
+****************************************************************************/
+void cmd_reg_enum(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res1 = True;
+       BOOL res2 = True;
+       int i;
+
+       POLICY_HND key_pol;
+       fstring full_keyname;
+       fstring key_name;
+
+       /*
+        * query key info
+        */
+
+       fstring key_class;
+       uint32 max_class_len = 0;
+       uint32 num_subkeys;
+       uint32 max_subkeylen;
+       uint32 max_subkeysize; 
+       uint32 num_values;
+       uint32 max_valnamelen;
+       uint32 max_valbufsize;
+       uint32 sec_desc;
+       NTTIME mod_time;
+
+       /*
+        * unknown 0x1a request
+        */
+
+       uint32 unk_1a_response;
+
+       DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "regenum <key_name>\n");
+               return;
+       }
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res1 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
+
+       res1 = res1 ? do_reg_query_key(smb_cli,
+                               &key_pol,
+                               key_class, &max_class_len,
+                               &num_subkeys, &max_subkeylen, &max_subkeysize,
+                               &num_values, &max_valnamelen, &max_valbufsize,
+                               &sec_desc, &mod_time) : False;
+
+       if (res1 && num_subkeys > 0)
+       {
+               fprintf(out_hnd,"Subkeys\n");
+               fprintf(out_hnd,"-------\n");
+       }
+
+       for (i = 0; i < num_subkeys; i++)
+       {
+               /*
+                * enumerate key
+                */
+
+               fstring enum_name;
+               uint32 enum_unk1;
+               uint32 enum_unk2;
+               time_t key_mod_time;
+
+               /* unknown 1a it */
+               res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol,
+                                       &unk_1a_response) : False;
+
+               if (res2 && unk_1a_response != 5)
+               {
+                       fprintf(out_hnd,"Unknown 1a response: %x\n", unk_1a_response);
+               }
+
+               /* enum key */
+               res2 = res2 ? do_reg_enum_key(smb_cli, &key_pol,
+                                       i, enum_name,
+                                       &enum_unk1, &enum_unk2,
+                                       &key_mod_time) : False;
+               
+               if (res2)
+               {
+                       display_reg_key_info(out_hnd, ACTION_HEADER   , enum_name, key_mod_time);
+                       display_reg_key_info(out_hnd, ACTION_ENUMERATE, enum_name, key_mod_time);
+                       display_reg_key_info(out_hnd, ACTION_FOOTER   , enum_name, key_mod_time);
+               }
+
+       }
+
+       if (num_values > 0)
+       {
+               fprintf(out_hnd,"Key Values\n");
+               fprintf(out_hnd,"----------\n");
+       }
+
+       for (i = 0; i < num_values; i++)
+       {
+               /*
+                * enumerate key
+                */
+
+               uint32 val_type;
+               BUFFER2 value;
+               fstring val_name;
+
+               /* unknown 1a it */
+               res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol,
+                                       &unk_1a_response) : False;
+
+               if (res2 && unk_1a_response != 5)
+               {
+                       fprintf(out_hnd,"Unknown 1a response: %x\n", unk_1a_response);
+               }
+
+               /* enum key */
+               res2 = res2 ? do_reg_enum_val(smb_cli, &key_pol,
+                                       i, max_valnamelen, max_valbufsize,
+                                       val_name, &val_type, &value) : False;
+               
+               if (res2)
+               {
+                       display_reg_value_info(out_hnd, ACTION_HEADER   , val_name, val_type, &value);
+                       display_reg_value_info(out_hnd, ACTION_ENUMERATE, val_name, val_type, &value);
+                       display_reg_value_info(out_hnd, ACTION_FOOTER   , val_name, val_type, &value);
+               }
+       }
+
+       /* close the handles */
+       if ((*key_name) != 0)
+       {
+               res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
+       }
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res1 && res2)
+       {
+               DEBUG(5,("cmd_reg_enum: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_enum: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry query key
+****************************************************************************/
+void cmd_reg_query_key(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res1 = True;
+
+       POLICY_HND key_pol;
+       fstring full_keyname;
+       fstring key_name;
+
+       /*
+        * query key info
+        */
+
+       fstring key_class;
+       uint32 key_class_len = 0;
+       uint32 num_subkeys;
+       uint32 max_subkeylen;
+       uint32 max_subkeysize; 
+       uint32 num_values;
+       uint32 max_valnamelen;
+       uint32 max_valbufsize;
+       uint32 sec_desc;
+       NTTIME mod_time;
+
+       DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "regquery key_name\n");
+               return;
+       }
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res1 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
+
+       res1 = res1 ? do_reg_query_key(smb_cli,
+                               &key_pol,
+                               key_class, &key_class_len,
+                               &num_subkeys, &max_subkeylen, &max_subkeysize,
+                               &num_values, &max_valnamelen, &max_valbufsize,
+                               &sec_desc, &mod_time) : False;
+
+       if (res1 && key_class_len != 0)
+       {
+               res1 = res1 ? do_reg_query_key(smb_cli,
+                               &key_pol,
+                               key_class, &key_class_len,
+                               &num_subkeys, &max_subkeylen, &max_subkeysize,
+                               &num_values, &max_valnamelen, &max_valbufsize,
+                               &sec_desc, &mod_time) : False;
+       }
+
+       if (res1)
+       {
+               fprintf(out_hnd,"Registry Query Info Key\n");
+               fprintf(out_hnd,"key class: %s\n", key_class);
+               fprintf(out_hnd,"subkeys, max_len, max_size: %d %d %d\n", num_subkeys, max_subkeylen, max_subkeysize);
+               fprintf(out_hnd,"vals, max_len, max_size: 0x%x 0x%x 0x%x\n", num_values, max_valnamelen, max_valbufsize);
+               fprintf(out_hnd,"sec desc: 0x%x\n", sec_desc);
+               fprintf(out_hnd,"mod time: %s\n", http_timestring(nt_time_to_unix(&mod_time)));
+       }
+
+       /* close the handles */
+       if ((*key_name) != 0)
+       {
+               res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
+       }
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res1)
+       {
+               DEBUG(5,("cmd_reg_query: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_query: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry create value
+****************************************************************************/
+void cmd_reg_create_val(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND parent_pol;
+       fstring full_keyname;
+       fstring keyname;
+       fstring parent_name;
+       fstring val_name;
+       fstring tmp;
+       uint32 val_type;
+       BUFFER3 value;
+
+#if 0
+       uint32 unk_0;
+       uint32 unk_1;
+       /* query it */
+       res1 = res1 ? do_reg_query_info(smb_cli, &val_pol,
+                               type, &unk_0, &unk_1) : False;
+#endif
+
+       DEBUG(5, ("cmd_reg_create_val: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "regcreate <val_name> <val_type> <val>\n");
+               return;
+       }
+
+       reg_get_subkey(full_keyname, keyname, val_name);
+
+       if (keyname[0] == 0 || val_name[0] == 0)
+       {
+               fprintf(out_hnd, "invalid key name\n");
+               return;
+       }
+       
+       if (!next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
+               return;
+       }
+
+       val_type = atoi(tmp);
+
+       if (val_type != 1 && val_type != 3 && val_type != 4)
+       {
+               fprintf(out_hnd, "val_type 1=UNISTR, 3=BYTES, 4=DWORD supported\n");
+               return;
+       }
+
+       if (!next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
+               return;
+       }
+
+       switch (val_type)
+       {
+               case 0x01: /* UNISTR */
+               {
+                       make_buffer3_str(&value, tmp, strlen(tmp)+1);
+                       break;
+               }
+               case 0x03: /* BYTES */
+               {
+                       make_buffer3_hex(&value, tmp);
+                       break;
+               }
+               case 0x04: /* DWORD */
+               {
+                       uint32 tmp_val;
+                       if (strnequal(tmp, "0x", 2))
+                       {
+                               tmp_val = strtol(tmp, (char**)NULL, 16);
+                       }
+                       else
+                       {
+                               tmp_val = strtol(tmp, (char**)NULL, 10);
+                       }
+                       make_buffer3_uint32(&value, tmp_val);
+                       break;
+               }
+               default:
+               {
+                       fprintf(out_hnd, "i told you i only deal with UNISTR, DWORD and BYTES!\n");
+                       return;
+               }
+       }
+               
+       DEBUG(10,("key data:\n"));
+       dump_data(10, (char *)value.buffer, value.buf_len);
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, keyname, parent_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*val_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        parent_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
+
+       /* create an entry */
+       res4 = res3 ? do_reg_create_val(smb_cli, &parent_pol,
+                                val_name, val_type, &value) : False;
+
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+       /* close the val handle */
+       if ((*val_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+       }
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_create_val: query succeeded\n"));
+               fprintf(out_hnd,"OK\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_create_val: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry delete value
+****************************************************************************/
+void cmd_reg_delete_val(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND parent_pol;
+       fstring full_keyname;
+       fstring keyname;
+       fstring parent_name;
+       fstring val_name;
+
+       DEBUG(5, ("cmd_reg_delete_val: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "regdelete <val_name>\n");
+               return;
+       }
+
+       reg_get_subkey(full_keyname, keyname, val_name);
+
+       if (keyname[0] == 0 || val_name[0] == 0)
+       {
+               fprintf(out_hnd, "invalid key name\n");
+               return;
+       }
+       
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, keyname, parent_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*val_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        parent_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
+
+       /* delete an entry */
+       res4 = res3 ? do_reg_delete_val(smb_cli, &parent_pol, val_name) : False;
+
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+       /* close the key handle */
+       res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_delete_val: query succeeded\n"));
+               fprintf(out_hnd,"OK\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_delete_val: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry delete key
+****************************************************************************/
+void cmd_reg_delete_key(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND parent_pol;
+       fstring full_keyname;
+       fstring parent_name;
+       fstring key_name;
+       fstring subkey_name;
+
+       DEBUG(5, ("cmd_reg_delete_key: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "regdeletekey <key_name>\n");
+               return;
+       }
+
+       reg_get_subkey(full_keyname, parent_name, subkey_name);
+
+       if (parent_name[0] == 0 || subkey_name[0] == 0)
+       {
+               fprintf(out_hnd, "invalid key name\n");
+               return;
+       }
+       
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, parent_name, key_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
+
+       /* create an entry */
+       res4 = res3 ? do_reg_delete_key(smb_cli, &parent_pol, subkey_name) : False;
+
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+       /* close the key handle */
+       if ((*key_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+       }
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_delete_key: query succeeded\n"));
+               fprintf(out_hnd,"OK\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_delete_key: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry create key
+****************************************************************************/
+void cmd_reg_create_key(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND parent_pol;
+       POLICY_HND key_pol;
+       fstring full_keyname;
+       fstring parent_key;
+       fstring parent_name;
+       fstring key_name;
+       fstring key_class;
+       SEC_ACCESS sam_access;
+
+       DEBUG(5, ("cmd_reg_create_key: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "regcreate <key_name> [key_class]\n");
+               return;
+       }
+
+       reg_get_subkey(full_keyname, parent_key, key_name);
+
+       if (parent_key[0] == 0 || key_name[0] == 0)
+       {
+               fprintf(out_hnd, "invalid key name\n");
+               return;
+       }
+       
+       if (!next_token(NULL, key_class, NULL, sizeof(key_class)))
+       {
+               memset(key_class, 0, sizeof(key_class));
+       }
+
+       /* set access permissions */
+       sam_access.mask = SEC_RIGHTS_READ;
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, parent_key, parent_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*parent_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        parent_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
+
+       /* create an entry */
+       res4 = res3 ? do_reg_create_key(smb_cli, &parent_pol,
+                                key_name, key_class, &sam_access, &key_pol) : False;
+
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, &parent_pol) : False;
+
+       /* close the key handle */
+       res4 = res4 ? do_reg_close(smb_cli, &key_pol) : False;
+
+       /* close the key handle */
+       if ((*parent_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+       }
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_create_key: query succeeded\n"));
+               fprintf(out_hnd,"OK\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_create_key: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry security info
+****************************************************************************/
+void cmd_reg_test_key_sec(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND key_pol;
+       fstring full_keyname;
+       fstring key_name;
+
+       /*
+        * security info
+        */
+
+       uint32 sec_buf_size;
+       SEC_DESC_BUF *psdb;
+
+       DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "reggetsec <key_name>\n");
+               return;
+       }
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
+
+       /* open an entry */
+       res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                key_name, 0x02000000, &key_pol) : False;
+
+       /* query key sec info.  first call sets sec_buf_size. */
+
+       sec_buf_size = 0;
+       res4 = res3 ? do_reg_get_key_sec(smb_cli, &key_pol,
+                               &sec_buf_size, &psdb) : False;
+       
+       free_sec_desc_buf(&psdb);
+
+       res4 = res4 ? do_reg_get_key_sec(smb_cli, &key_pol,
+                               &sec_buf_size, &psdb) : False;
+
+       if (res4 && psdb->len > 0 && psdb->sec != NULL)
+       {
+               display_sec_desc(out_hnd, ACTION_HEADER   , psdb->sec);
+               display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
+               display_sec_desc(out_hnd, ACTION_FOOTER   , psdb->sec);
+
+               res4 = res4 ? do_reg_set_key_sec(smb_cli, &key_pol, psdb) : False;
+       }
+
+       free_sec_desc_buf(&psdb);
+
+       /* close the key handle */
+       if ((*key_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, &key_pol) : False;
+       }
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_test2: query succeeded\n"));
+               fprintf(out_hnd,"Registry Test2\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_test2: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry security info
+****************************************************************************/
+void cmd_reg_get_key_sec(struct client_info *info)
+{
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND key_pol;
+       fstring full_keyname;
+       fstring key_name;
+
+       /*
+        * security info
+        */
+
+       uint32 sec_buf_size;
+       SEC_DESC_BUF *psdb;
+
+       DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "reggetsec <key_name>\n");
+               return;
+       }
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, full_keyname, key_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
+
+       /* open an entry */
+       res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+                                key_name, 0x02000000, &key_pol) : False;
+
+       /* Get the size. */
+       sec_buf_size = 0;
+       res4 = res3 ? do_reg_get_key_sec(smb_cli, &key_pol,
+                               &sec_buf_size, &psdb) : False;
+       
+       free_sec_desc_buf(&psdb);
+
+       res4 = res4 ? do_reg_get_key_sec(smb_cli, &key_pol,
+                               &sec_buf_size, &psdb) : False;
+
+       if (res4 && psdb->len > 0 && psdb->sec != NULL)
+       {
+               display_sec_desc(out_hnd, ACTION_HEADER   , psdb->sec);
+               display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
+               display_sec_desc(out_hnd, ACTION_FOOTER   , psdb->sec);
+       }
+
+       free_sec_desc_buf(&psdb);
+
+       /* close the key handle */
+       if ((*key_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, &key_pol) : False;
+       }
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_get_key_sec: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_get_key_sec: query failed\n"));
+       }
+}
index 24f59b4f640c1947b2d4df87a7fe52c0bef7e50f..eeb34c8f887bcd0e71ff0c6df723b1e1aa256052 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+#define DEBUG_TESTING
+
+extern struct cli_state *smb_cli;
+
+extern FILE* out_hnd;
+
+
+/****************************************************************************
+SAM password change
+****************************************************************************/
+void cmd_sam_ntchange_pwd(struct client_info *info)
+{
+       fstring srv_name;
+       fstring domain;
+       fstring sid;
+       char *new_passwd;
+       BOOL res = True;
+       char nt_newpass[516];
+       uchar nt_hshhash[16];
+       uchar nt_newhash[16];
+       uchar nt_oldhash[16];
+       char lm_newpass[516];
+       uchar lm_newhash[16];
+       uchar lm_hshhash[16];
+       uchar lm_oldhash[16];
+
+       sid_to_string(sid, &info->dom.level5_sid);
+       fstrcpy(domain, info->dom.level5_dom);
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       fprintf(out_hnd, "SAM NT Password Change\n");
+
+#if 0
+       struct pwd_info new_pwd;
+       pwd_read(&new_pwd, "New Password (ONCE: this is test code!):", True);
+#endif
+       new_passwd = (char*)getpass("New Password (ONCE ONLY - get it right :-)");
+
+       nt_lm_owf_gen(new_passwd, lm_newhash, nt_newhash);
+       pwd_get_lm_nt_16(&(smb_cli->pwd), lm_oldhash, nt_oldhash );
+       make_oem_passwd_hash(nt_newpass, new_passwd, nt_oldhash, True);
+       make_oem_passwd_hash(lm_newpass, new_passwd, lm_oldhash, True);
+       E_old_pw_hash(lm_newhash, lm_oldhash, lm_hshhash);
+       E_old_pw_hash(lm_newhash, nt_oldhash, nt_hshhash);
+
+       cli_nt_set_ntlmssp_flgs(smb_cli,
+                                   NTLMSSP_NEGOTIATE_UNICODE |
+                                   NTLMSSP_NEGOTIATE_OEM |
+                                   NTLMSSP_NEGOTIATE_SIGN |
+                                   NTLMSSP_NEGOTIATE_SEAL |
+                                   NTLMSSP_NEGOTIATE_LM_KEY |
+                                   NTLMSSP_NEGOTIATE_NTLM |
+                                   NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
+                                   NTLMSSP_NEGOTIATE_00001000 |
+                                   NTLMSSP_NEGOTIATE_00002000);
+
+       /* open SAMR session.  */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR) : False;
+
+       /* establish a connection. */
+       res = res ? do_samr_unknown_38(smb_cli, srv_name) : False;
+
+       /* establish a connection. */
+       res = res ? do_samr_chgpasswd_user(smb_cli,
+                                          srv_name, smb_cli->user_name,
+                                          nt_newpass, nt_hshhash,
+                                          lm_newpass, lm_hshhash) : False;
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               fprintf(out_hnd, "NT Password changed OK\n");
+       }
+       else
+       {
+               fprintf(out_hnd, "NT Password change FAILED\n");
+       }
+}
+
+
+/****************************************************************************
+experimental SAM encryted rpc test connection
+****************************************************************************/
+void cmd_sam_test(struct client_info *info)
+{
+       fstring srv_name;
+       fstring domain;
+       fstring sid;
+       BOOL res = True;
+
+       sid_to_string(sid, &info->dom.level5_sid);
+       fstrcpy(domain, info->dom.level5_dom);
+
+/*
+       if (strlen(sid) == 0)
+       {
+               fprintf(out_hnd, "please use 'lsaquery' first, to ascertain the SID\n");
+               return;
+       }
+*/
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       fprintf(out_hnd, "SAM Encryption Test\n");
+
+       cli_nt_set_ntlmssp_flgs(smb_cli,
+                                   NTLMSSP_NEGOTIATE_UNICODE |
+                                   NTLMSSP_NEGOTIATE_OEM |
+                                   NTLMSSP_NEGOTIATE_SIGN |
+                                   NTLMSSP_NEGOTIATE_SEAL |
+                                   NTLMSSP_NEGOTIATE_LM_KEY |
+                                   NTLMSSP_NEGOTIATE_NTLM |
+                                   NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
+                                   NTLMSSP_NEGOTIATE_00001000 |
+                                   NTLMSSP_NEGOTIATE_00002000);
+
+       /* open SAMR session.  */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR) : False;
+
+       /* establish a connection. */
+       res = res ? do_samr_unknown_38(smb_cli, srv_name) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_sam_test: succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_sam_test: failed\n"));
+       }
+}
+
+
+/****************************************************************************
+experimental SAM users enum.
+****************************************************************************/
+void cmd_sam_enum_users(struct client_info *info)
+{
+       fstring srv_name;
+       fstring domain;
+       fstring sid;
+       DOM_SID sid1;
+       int user_idx;
+       BOOL res = True;
+       BOOL request_user_info  = False;
+       BOOL request_group_info = False;
+       uint16 num_entries = 0;
+       uint16 unk_0 = 0x0;
+       uint16 acb_mask = 0;
+       uint16 unk_1 = 0x0;
+       uint32 admin_rid = 0x304; /* absolutely no idea. */
+       fstring tmp;
+
+       sid_to_string(sid, &info->dom.level5_sid);
+       fstrcpy(domain, info->dom.level5_dom);
+
+       if (strlen(sid) == 0)
+       {
+               fprintf(out_hnd, "please use 'lsaquery' first, to ascertain the SID\n");
+               return;
+       }
+
+       make_dom_sid(&sid1, sid);
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       /* a bad way to do token parsing... */
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               request_user_info  |= strequal(tmp, "-u");
+               request_group_info |= strequal(tmp, "-g");
+       }
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               request_user_info  |= strequal(tmp, "-u");
+               request_group_info |= strequal(tmp, "-g");
+       }
+
+#ifdef DEBUG_TESTING
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               num_entries = (uint16)strtol(tmp, (char**)NULL, 16);
+       }
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               unk_0 = (uint16)strtol(tmp, (char**)NULL, 16);
+       }
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               acb_mask = (uint16)strtol(tmp, (char**)NULL, 16);
+       }
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               unk_1 = (uint16)strtol(tmp, (char**)NULL, 16);
+       }
+#endif
+
+       fprintf(out_hnd, "SAM Enumerate Users\n");
+       fprintf(out_hnd, "From: %s To: %s Domain: %s SID: %s\n",
+                         info->myhostname, srv_name, domain, sid);
+
+#ifdef DEBUG_TESTING
+       DEBUG(5,("Number of entries:%d unk_0:%04x acb_mask:%04x unk_1:%04x\n",
+                 num_entries, unk_0, acb_mask, unk_1));
+#endif
+
+       /* open SAMR session.  negotiate credentials */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR) : False;
+
+       /* establish a connection. */
+       res = res ? do_samr_connect(smb_cli, 
+                               srv_name, 0x00000020,
+                               &info->dom.samr_pol_connect) : False;
+
+       /* connect to the domain */
+       res = res ? do_samr_open_domain(smb_cli, 
+                   &info->dom.samr_pol_connect, admin_rid, &sid1,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       /* read some users */
+       res = res ? do_samr_enum_dom_users(smb_cli, 
+                               &info->dom.samr_pol_open_domain,
+                   num_entries, unk_0, acb_mask, unk_1, 0xffff,
+                               &info->dom.sam, &info->dom.num_sam_entries) : False;
+
+       if (res && info->dom.num_sam_entries == 0)
+       {
+               fprintf(out_hnd, "No users\n");
+       }
+
+       if (request_user_info || request_group_info)
+       {
+               /* query all the users */
+               user_idx = 0;
+
+               while (res && user_idx < info->dom.num_sam_entries)
+               {
+                       uint32 user_rid = info->dom.sam[user_idx].smb_userid;
+                       SAM_USER_INFO_21 usr;
+
+                       fprintf(out_hnd, "User RID: %8x  User Name: %s\n",
+                                         user_rid,
+                                         info->dom.sam[user_idx].acct_name);
+
+                       if (request_user_info)
+                       {
+                               /* send user info query, level 0x15 */
+                               if (get_samr_query_userinfo(smb_cli,
+                                                       &info->dom.samr_pol_open_domain,
+                                                       0x15, user_rid, &usr))
+                               {
+                                       display_sam_user_info_21(out_hnd, ACTION_HEADER   , &usr);
+                                       display_sam_user_info_21(out_hnd, ACTION_ENUMERATE, &usr);
+                                       display_sam_user_info_21(out_hnd, ACTION_FOOTER   , &usr);
+                               }
+                       }
+
+                       if (request_group_info)
+                       {
+                               uint32 num_groups;
+                               DOM_GID gid[LSA_MAX_GROUPS];
+
+                               /* send user group query */
+                               if (get_samr_query_usergroups(smb_cli,
+                                                       &info->dom.samr_pol_open_domain,
+                                                       user_rid, &num_groups, gid))
+                               {
+                                       display_group_rid_info(out_hnd, ACTION_HEADER   , num_groups, gid);
+                                       display_group_rid_info(out_hnd, ACTION_ENUMERATE, num_groups, gid);
+                                       display_group_rid_info(out_hnd, ACTION_FOOTER   , num_groups, gid);
+                               }
+                       }
+
+                       user_idx++;
+               }
+       }
+
+       res = res ? do_samr_close(smb_cli,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       res = res ? do_samr_close(smb_cli,
+                   &info->dom.samr_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (info->dom.sam != NULL)
+       {
+               free(info->dom.sam);
+       }
+
+       if (res)
+       {
+               DEBUG(5,("cmd_sam_enum_users: succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_sam_enum_users: failed\n"));
+       }
+}
+
+
+/****************************************************************************
+experimental SAM user query.
+****************************************************************************/
+void cmd_sam_query_user(struct client_info *info)
+{
+       fstring srv_name;
+       fstring domain;
+       fstring sid;
+       DOM_SID sid1;
+       int user_idx = 0;  /* FIXME maybe ... */
+       BOOL res = True;
+       uint32 admin_rid = 0x304; /* absolutely no idea. */
+       fstring rid_str ;
+       fstring info_str;
+       uint32 user_rid = 0;
+       uint32 info_level = 0x15;
+
+       SAM_USER_INFO_21 usr;
+
+       sid_to_string(sid, &info->dom.level5_sid);
+       fstrcpy(domain, info->dom.level5_dom);
+
+       if (strlen(sid) == 0)
+       {
+               fprintf(out_hnd, "please use 'lsaquery' first, to ascertain the SID\n");
+               return;
+       }
+
+       make_dom_sid(&sid1, sid);
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       if (next_token(NULL, rid_str , NULL, sizeof(rid_str )) &&
+           next_token(NULL, info_str, NULL, sizeof(info_str)))
+       {
+               user_rid   = (uint32)strtol(rid_str , (char**)NULL, 16);
+               info_level = (uint32)strtol(info_str, (char**)NULL, 10);
+       }
+
+       fprintf(out_hnd, "SAM Query User: rid %x info level %d\n",
+                         user_rid, info_level);
+       fprintf(out_hnd, "From: %s To: %s Domain: %s SID: %s\n",
+                         info->myhostname, srv_name, domain, sid);
+
+       /* open SAMR session.  negotiate credentials */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR) : False;
+
+       /* establish a connection. */
+       res = res ? do_samr_connect(smb_cli,
+                               srv_name, 0x00000020,
+                               &info->dom.samr_pol_connect) : False;
+
+       /* connect to the domain */
+       res = res ? do_samr_open_domain(smb_cli,
+                   &info->dom.samr_pol_connect, admin_rid, &sid1,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       fprintf(out_hnd, "User RID: %8x  User Name: %s\n",
+                         user_rid,
+                         info->dom.sam[user_idx].acct_name);
+
+       /* send user info query, level */
+       if (get_samr_query_userinfo(smb_cli,
+                                       &info->dom.samr_pol_open_domain,
+                                       info_level, user_rid, &usr))
+       {
+               if (info_level == 0x15)
+               {
+                       display_sam_user_info_21(out_hnd, ACTION_HEADER   , &usr);
+                       display_sam_user_info_21(out_hnd, ACTION_ENUMERATE, &usr);
+                       display_sam_user_info_21(out_hnd, ACTION_FOOTER   , &usr);
+               }
+       }
+
+       res = res ? do_samr_close(smb_cli,
+                   &info->dom.samr_pol_connect) : False;
+
+       res = res ? do_samr_close(smb_cli,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_sam_query_user: succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_sam_query_user: failed\n"));
+       }
+}
+
+
+/****************************************************************************
+experimental SAM groups query.
+****************************************************************************/
+void cmd_sam_query_groups(struct client_info *info)
+{
+       fstring srv_name;
+       fstring domain;
+       fstring sid;
+       DOM_SID sid1;
+       BOOL res = True;
+       fstring info_str;
+       uint32 switch_value = 2;
+       uint32 admin_rid = 0x304; /* absolutely no idea. */
+
+       sid_to_string(sid, &info->dom.level5_sid);
+       fstrcpy(domain, info->dom.level5_dom);
+
+       if (strlen(sid) == 0)
+       {
+               fprintf(out_hnd, "please use 'lsaquery' first, to ascertain the SID\n");
+               return;
+       }
+
+       make_dom_sid(&sid1, sid);
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       if (next_token(NULL, info_str, NULL, sizeof(info_str)))
+       {
+               switch_value = (uint32)strtol(info_str, (char**)NULL, 10);
+       }
+
+       fprintf(out_hnd, "SAM Query Groups: info level %d\n", switch_value);
+       fprintf(out_hnd, "From: %s To: %s Domain: %s SID: %s\n",
+                         info->myhostname, srv_name, domain, sid);
+
+       /* open SAMR session.  negotiate credentials */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR) : False;
+
+       /* establish a connection. */
+       res = res ? do_samr_connect(smb_cli, 
+                               srv_name, 0x00000020,
+                               &info->dom.samr_pol_connect) : False;
+
+       /* connect to the domain */
+       res = res ? do_samr_open_domain(smb_cli, 
+                   &info->dom.samr_pol_connect, admin_rid, &sid1,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       /* send a samr 0x8 command */
+       res = res ? do_samr_query_dom_info(smb_cli,
+                   &info->dom.samr_pol_open_domain, switch_value) : False;
+
+       res = res ? do_samr_close(smb_cli,
+                   &info->dom.samr_pol_connect) : False;
+
+       res = res ? do_samr_close(smb_cli, 
+                   &info->dom.samr_pol_open_domain) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_sam_query_groups: succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_sam_query_groups: failed\n"));
+       }
+}
+
+
+/****************************************************************************
+experimental SAM aliases query.
+****************************************************************************/
+void cmd_sam_enum_aliases(struct client_info *info)
+{
+       fstring srv_name;
+       fstring domain;
+       fstring sid;
+       DOM_SID sid1;
+       BOOL res = True;
+       BOOL request_user_info  = False;
+       BOOL request_alias_info = False;
+       uint32 admin_rid = 0x304; /* absolutely no idea. */
+       fstring tmp;
+
+       uint32 num_aliases = 3;
+       uint32 alias_rid[3] = { DOMAIN_GROUP_RID_ADMINS, DOMAIN_GROUP_RID_USERS, DOMAIN_GROUP_RID_GUESTS };
+       fstring alias_names [3];
+       uint32  num_als_usrs[3];
+
+       sid_to_string(sid, &info->dom.level3_sid);
+       fstrcpy(domain, info->dom.level3_dom);
+#if 0
+       fstrcpy(sid   , "S-1-5-20");
+#endif
+       if (strlen(sid) == 0)
+       {
+               fprintf(out_hnd, "please use 'lsaquery' first, to ascertain the SID\n");
+               return;
+       }
+
+       make_dom_sid(&sid1, sid);
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       /* a bad way to do token parsing... */
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               request_user_info  |= strequal(tmp, "-u");
+               request_alias_info |= strequal(tmp, "-g");
+       }
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               request_user_info  |= strequal(tmp, "-u");
+               request_alias_info |= strequal(tmp, "-g");
+       }
+
+       fprintf(out_hnd, "SAM Enumerate Aliases\n");
+       fprintf(out_hnd, "From: %s To: %s Domain: %s SID: %s\n",
+                         info->myhostname, srv_name, domain, sid);
+
+       /* open SAMR session.  negotiate credentials */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR) : False;
+
+       /* establish a connection. */
+       res = res ? do_samr_connect(smb_cli,
+                               srv_name, 0x00000020,
+                               &info->dom.samr_pol_connect) : False;
+
+       /* connect to the domain */
+       res = res ? do_samr_open_domain(smb_cli,
+                   &info->dom.samr_pol_connect, admin_rid, &sid1,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       /* send a query on the aliase */
+       res = res ? do_samr_query_unknown_12(smb_cli,
+                   &info->dom.samr_pol_open_domain, admin_rid, num_aliases, alias_rid,
+                   &num_aliases, alias_names, num_als_usrs) : False;
+
+       if (res)
+       {
+               display_alias_name_info(out_hnd, ACTION_HEADER   , num_aliases, alias_names, num_als_usrs);
+               display_alias_name_info(out_hnd, ACTION_ENUMERATE, num_aliases, alias_names, num_als_usrs);
+               display_alias_name_info(out_hnd, ACTION_FOOTER   , num_aliases, alias_names, num_als_usrs);
+       }
+
+#if 0
+
+       /* read some users */
+       res = res ? do_samr_enum_dom_users(smb_cli,
+                               &info->dom.samr_pol_open_domain,
+                   num_entries, unk_0, acb_mask, unk_1, 0xffff,
+                               info->dom.sam, &info->dom.num_sam_entries) : False;
+
+       if (res && info->dom.num_sam_entries == 0)
+       {
+               fprintf(out_hnd, "No users\n");
+       }
+
+       if (request_user_info || request_alias_info)
+       {
+               /* query all the users */
+               user_idx = 0;
+
+               while (res && user_idx < info->dom.num_sam_entries)
+               {
+                       uint32 user_rid = info->dom.sam[user_idx].smb_userid;
+                       SAM_USER_INFO_21 usr;
+
+                       fprintf(out_hnd, "User RID: %8x  User Name: %s\n",
+                                         user_rid,
+                                         info->dom.sam[user_idx].acct_name);
+
+                       if (request_user_info)
+                       {
+                               /* send user info query, level 0x15 */
+                               if (get_samr_query_userinfo(smb_cli,
+                                                       &info->dom.samr_pol_open_domain,
+                                                       0x15, user_rid, &usr))
+                               {
+                                       display_sam_user_info_21(out_hnd, ACTION_HEADER   , &usr);
+                                       display_sam_user_info_21(out_hnd, ACTION_ENUMERATE, &usr);
+                                       display_sam_user_info_21(out_hnd, ACTION_FOOTER   , &usr);
+                               }
+                       }
+
+                       if (request_alias_info)
+                       {
+                               uint32 num_aliases;
+                               DOM_GID gid[LSA_MAX_GROUPS];
+
+                               /* send user aliase query */
+                               if (get_samr_query_useraliases(smb_cli, 
+                                                       &info->dom.samr_pol_open_domain,
+                                                       user_rid, &num_aliases, gid))
+                               {
+                                       display_alias_info(out_hnd, ACTION_HEADER   , num_aliases, gid);
+                                       display_alias_info(out_hnd, ACTION_ENUMERATE, num_aliases, gid);
+                                       display_alias_info(out_hnd, ACTION_FOOTER   , num_aliases, gid);
+                               }
+                       }
+
+                       user_idx++;
+               }
+       }
+#endif
+
+       res = res ? do_samr_close(smb_cli, 
+                   &info->dom.samr_pol_connect) : False;
+
+       res = res ? do_samr_close(smb_cli,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_sam_enum_users: succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_sam_enum_users: failed\n"));
+       }
+}
+
+
index 24f59b4f640c1947b2d4df87a7fe52c0bef7e50f..9e3fd845bb6640cd66e19b07ed2e2dbc000b734a 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+#define DEBUG_TESTING
+
+extern struct cli_state *smb_cli;
+
+extern FILE* out_hnd;
+
+
+/****************************************************************************
+server get info query
+****************************************************************************/
+void cmd_srv_query_info(struct client_info *info)
+{
+       fstring dest_srv;
+       fstring tmp;
+       SRV_INFO_CTR ctr;
+       uint32 info_level = 101;
+
+       BOOL res = True;
+
+       memset((char *)&ctr, '\0', sizeof(ctr));
+
+       fstrcpy(dest_srv, "\\\\");
+       fstrcat(dest_srv, info->dest_host);
+       strupper(dest_srv);
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)-1))
+       {
+               info_level = (uint32)strtol(tmp, (char**)NULL, 10);
+       }
+
+       DEBUG(4,("cmd_srv_query_info: server:%s info level: %d\n",
+                               dest_srv, (int)info_level));
+
+       DEBUG(5, ("cmd_srv_query_info: smb_cli->fd:%d\n", smb_cli->fd));
+
+       /* open LSARPC session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SRVSVC) : False;
+
+       /* send info level: receive requested info.  hopefully. */
+       res = res ? do_srv_net_srv_get_info(smb_cli,
+                               dest_srv, info_level, &ctr) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_srv_query_info: query succeeded\n"));
+
+               display_srv_info_ctr(out_hnd, ACTION_HEADER   , &ctr);
+               display_srv_info_ctr(out_hnd, ACTION_ENUMERATE, &ctr);
+               display_srv_info_ctr(out_hnd, ACTION_FOOTER   , &ctr);
+       }
+       else
+       {
+               DEBUG(5,("cmd_srv_query_info: query failed\n"));
+       }
+}
+
+/****************************************************************************
+server enum connections
+****************************************************************************/
+void cmd_srv_enum_conn(struct client_info *info)
+{
+       fstring dest_srv;
+       fstring qual_srv;
+       fstring tmp;
+       SRV_CONN_INFO_CTR ctr;
+       ENUM_HND hnd;
+       uint32 info_level = 0;
+
+       BOOL res = True;
+
+       memset((char *)&ctr, '\0', sizeof(ctr));
+
+       fstrcpy(qual_srv, "\\\\");
+       fstrcat(qual_srv, info->myhostname);
+       strupper(qual_srv);
+
+       fstrcpy(dest_srv, "\\\\");
+       fstrcat(dest_srv, info->dest_host);
+       strupper(dest_srv);
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)-1))
+       {
+               info_level = (uint32)strtol(tmp, (char**)NULL, 10);
+       }
+
+       DEBUG(4,("cmd_srv_enum_conn: server:%s info level: %d\n",
+                               dest_srv, (int)info_level));
+
+       DEBUG(5, ("cmd_srv_enum_conn: smb_cli->fd:%d\n", smb_cli->fd));
+
+       /* open srvsvc session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SRVSVC) : False;
+
+       hnd.ptr_hnd = 1;
+       hnd.handle = 0;
+
+       /* enumerate connections on server */
+       res = res ? do_srv_net_srv_conn_enum(smb_cli,
+                               dest_srv, qual_srv,
+                   info_level, &ctr, 0xffffffff, &hnd) : False;
+
+       if (res)
+       {
+               display_srv_conn_info_ctr(out_hnd, ACTION_HEADER   , &ctr);
+               display_srv_conn_info_ctr(out_hnd, ACTION_ENUMERATE, &ctr);
+               display_srv_conn_info_ctr(out_hnd, ACTION_FOOTER   , &ctr);
+       }
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_srv_enum_conn: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_srv_enum_conn: query failed\n"));
+       }
+}
+
+/****************************************************************************
+server enum shares
+****************************************************************************/
+void cmd_srv_enum_shares(struct client_info *info)
+{
+       fstring dest_srv;
+       fstring tmp;
+       SRV_SHARE_INFO_CTR ctr;
+       ENUM_HND hnd;
+       uint32 info_level = 1;
+
+       BOOL res = True;
+
+       memset((char *)&ctr, '\0', sizeof(ctr));
+
+       fstrcpy(dest_srv, "\\\\");
+       fstrcat(dest_srv, info->dest_host);
+       strupper(dest_srv);
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)-1))
+       {
+               info_level = (uint32)strtol(tmp, (char**)NULL, 10);
+       }
+
+       DEBUG(4,("cmd_srv_enum_shares: server:%s info level: %d\n",
+                               dest_srv, (int)info_level));
+
+       DEBUG(5, ("cmd_srv_enum_shares: smb_cli->fd:%d\n", smb_cli->fd));
+
+       /* open srvsvc session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SRVSVC) : False;
+
+       hnd.ptr_hnd = 0;
+       hnd.handle = 0;
+
+       /* enumerate shares_files on server */
+       res = res ? do_srv_net_srv_share_enum(smb_cli,
+                               dest_srv, 
+                   info_level, &ctr, 0xffffffff, &hnd) : False;
+
+       if (res)
+       {
+               display_srv_share_info_ctr(out_hnd, ACTION_HEADER   , &ctr);
+               display_srv_share_info_ctr(out_hnd, ACTION_ENUMERATE, &ctr);
+               display_srv_share_info_ctr(out_hnd, ACTION_FOOTER   , &ctr);
+       }
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_srv_enum_shares: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_srv_enum_shares: query failed\n"));
+       }
+}
+
+/****************************************************************************
+server enum sessions
+****************************************************************************/
+void cmd_srv_enum_sess(struct client_info *info)
+{
+       fstring dest_srv;
+       fstring tmp;
+       SRV_SESS_INFO_CTR ctr;
+       ENUM_HND hnd;
+       uint32 info_level = 0;
+
+       BOOL res = True;
+
+       memset((char *)&ctr, '\0', sizeof(ctr));
+
+       fstrcpy(dest_srv, "\\\\");
+       fstrcat(dest_srv, info->dest_host);
+       strupper(dest_srv);
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)-1))
+       {
+               info_level = (uint32)strtol(tmp, (char**)NULL, 10);
+       }
+
+       DEBUG(4,("cmd_srv_enum_sess: server:%s info level: %d\n",
+                               dest_srv, (int)info_level));
+
+       DEBUG(5, ("cmd_srv_enum_sess: smb_cli->fd:%d\n", smb_cli->fd));
+
+       /* open srvsvc session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SRVSVC) : False;
+
+       hnd.ptr_hnd = 1;
+       hnd.handle = 0;
+
+       /* enumerate sessions on server */
+       res = res ? do_srv_net_srv_sess_enum(smb_cli,
+                               dest_srv, NULL, info_level, &ctr, 0x1000, &hnd) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_srv_enum_sess: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_srv_enum_sess: query failed\n"));
+       }
+}
+
+/****************************************************************************
+server enum files
+****************************************************************************/
+void cmd_srv_enum_files(struct client_info *info)
+{
+       fstring dest_srv;
+       fstring tmp;
+       SRV_FILE_INFO_CTR ctr;
+       ENUM_HND hnd;
+       uint32 info_level = 3;
+
+       BOOL res = True;
+
+       memset((char *)&ctr, '\0', sizeof(ctr));
+
+       fstrcpy(dest_srv, "\\\\");
+       fstrcat(dest_srv, info->dest_host);
+       strupper(dest_srv);
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)-1))
+       {
+               info_level = (uint32)strtol(tmp, (char**)NULL, 10);
+       }
+
+       DEBUG(4,("cmd_srv_enum_files: server:%s info level: %d\n",
+                               dest_srv, (int)info_level));
+
+       DEBUG(5, ("cmd_srv_enum_files: smb_cli->fd:%d\n", smb_cli->fd));
+
+       /* open srvsvc session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SRVSVC) : False;
+
+       hnd.ptr_hnd = 1;
+       hnd.handle = 0;
+
+       /* enumerate files on server */
+       res = res ? do_srv_net_srv_file_enum(smb_cli,
+                               dest_srv, NULL, info_level, &ctr, 0x1000, &hnd) : False;
+
+       if (res)
+       {
+               display_srv_file_info_ctr(out_hnd, ACTION_HEADER   , &ctr);
+               display_srv_file_info_ctr(out_hnd, ACTION_ENUMERATE, &ctr);
+               display_srv_file_info_ctr(out_hnd, ACTION_FOOTER   , &ctr);
+       }
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_srv_enum_files: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_srv_enum_files: query failed\n"));
+       }
+}
+
index 24f59b4f640c1947b2d4df87a7fe52c0bef7e50f..0b8f469af372625d51857c29e5feedeaba92d0ec 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+#define DEBUG_TESTING
+
+extern struct cli_state *smb_cli;
+
+extern FILE* out_hnd;
+
+
+/****************************************************************************
+workstation get info query
+****************************************************************************/
+void cmd_wks_query_info(struct client_info *info)
+{
+       fstring dest_wks;
+       fstring tmp;
+       WKS_INFO_100 ctr;
+       uint32 info_level = 100;
+
+       BOOL res = True;
+
+       memset((char *)&ctr, '\0', sizeof(ctr));
+
+       fstrcpy(dest_wks, "\\\\");
+       fstrcat(dest_wks, info->dest_host);
+       strupper(dest_wks);
+
+       if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               info_level = (uint32)strtol(tmp, (char**)NULL, 10);
+       }
+
+       DEBUG(4,("cmd_wks_query_info: server:%s info level: %d\n",
+                               dest_wks, info_level));
+
+       DEBUG(5, ("cmd_wks_query_info: smb_cli->fd:%d\n", smb_cli->fd));
+
+       /* open LSARPC session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WKSSVC) : False;
+
+       /* send info level: receive requested info.  hopefully. */
+       res = res ? do_wks_query_info(smb_cli, 
+                               dest_wks, info_level, &ctr) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_wks_query_info: query succeeded\n"));
+
+#if 0
+               display_wks_info_100(out_hnd, ACTION_HEADER   , &ctr);
+               display_wks_info_100(out_hnd, ACTION_ENUMERATE, &ctr);
+               display_wks_info_100(out_hnd, ACTION_FOOTER   , &ctr);
+#endif
+
+       }
+       else
+       {
+               DEBUG(5,("cmd_wks_query_info: query failed\n"));
+       }
+}
+
index be16bc18c8810b2c73913474a844ad7b6d66cb55..75c9930ebb01c103b5afd53ef259940a807f81c9 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+#include "includes.h"
+
+
+/****************************************************************************
+convert a share mode to a string
+****************************************************************************/
+char *get_file_mode_str(uint32 share_mode)
+{
+       static fstring mode;
+
+       switch ((share_mode>>4)&0xF)
+       {
+               case DENY_NONE : fstrcpy(mode, "DENY_NONE  "); break;
+               case DENY_ALL  : fstrcpy(mode, "DENY_ALL   "); break;
+               case DENY_DOS  : fstrcpy(mode, "DENY_DOS   "); break;
+               case DENY_READ : fstrcpy(mode, "DENY_READ  "); break;
+               case DENY_WRITE: fstrcpy(mode, "DENY_WRITE "); break;
+               default        : fstrcpy(mode, "DENY_????  "); break;
+       }
+
+       switch (share_mode & 0xF)
+       {
+               case 0 : fstrcat(mode, "RDONLY"); break;
+               case 1 : fstrcat(mode, "WRONLY"); break;
+               case 2 : fstrcat(mode, "RDWR  "); break;
+               default: fstrcat(mode, "R??W??"); break;
+       }
+
+       return mode;
+}
+
+/****************************************************************************
+convert an oplock mode to a string
+****************************************************************************/
+char *get_file_oplock_str(uint32 op_type)
+{
+       static fstring oplock;
+       BOOL excl  = IS_BITS_SET_ALL(op_type, EXCLUSIVE_OPLOCK);
+       BOOL batch = IS_BITS_SET_ALL(op_type, BATCH_OPLOCK    );
+
+       oplock[0] = 0;
+
+       if (excl           ) fstrcat(oplock, "EXCLUSIVE");
+       if (excl  &&  batch) fstrcat(oplock, "+");
+       if (          batch) fstrcat(oplock, "BATCH");
+       if (!excl && !batch) fstrcat(oplock, "NONE");
+
+       return oplock;
+}
+
+/****************************************************************************
+convert a share type enum to a string
+****************************************************************************/
+char *get_share_type_str(uint32 type)
+{
+       static fstring typestr;
+
+       switch (type)
+       {
+               case STYPE_DISKTREE: fstrcpy(typestr, "Disk"   ); break;
+               case STYPE_PRINTQ  : fstrcpy(typestr, "Printer"); break;              
+               case STYPE_DEVICE  : fstrcpy(typestr, "Device" ); break;
+               case STYPE_IPC     : fstrcpy(typestr, "IPC"    ); break;      
+               default            : fstrcpy(typestr, "????"   ); break;      
+       }
+       return typestr;
+}
+
+/****************************************************************************
+convert a server type enum to a string
+****************************************************************************/
+char *get_server_type_str(uint32 type)
+{
+       static fstring typestr;
+
+       if (type == SV_TYPE_ALL)
+       {
+               fstrcpy(typestr, "All");
+       }
+       else
+       {
+               int i;
+               typestr[0] = 0;
+               for (i = 0; i < 32; i++)
+               {
+                       if (IS_BITS_SET_ALL(type, 1 << i))
+                       {
+                               switch (1 << i)
+                               {
+                                       case SV_TYPE_WORKSTATION      : fstrcat(typestr, "Wk " ); break;
+                                       case SV_TYPE_SERVER           : fstrcat(typestr, "Sv " ); break;
+                                       case SV_TYPE_SQLSERVER        : fstrcat(typestr, "Sql "); break;
+                                       case SV_TYPE_DOMAIN_CTRL      : fstrcat(typestr, "PDC "); break;
+                                       case SV_TYPE_DOMAIN_BAKCTRL   : fstrcat(typestr, "BDC "); break;
+                                       case SV_TYPE_TIME_SOURCE      : fstrcat(typestr, "Tim "); break;
+                                       case SV_TYPE_AFP              : fstrcat(typestr, "AFP "); break;
+                                       case SV_TYPE_NOVELL           : fstrcat(typestr, "Nov "); break;
+                                       case SV_TYPE_DOMAIN_MEMBER    : fstrcat(typestr, "Dom "); break;
+                                       case SV_TYPE_PRINTQ_SERVER    : fstrcat(typestr, "PrQ "); break;
+                                       case SV_TYPE_DIALIN_SERVER    : fstrcat(typestr, "Din "); break;
+                                       case SV_TYPE_SERVER_UNIX      : fstrcat(typestr, "Unx "); break;
+                                       case SV_TYPE_NT               : fstrcat(typestr, "NT " ); break;
+                                       case SV_TYPE_WFW              : fstrcat(typestr, "Wfw "); break;
+                                       case SV_TYPE_SERVER_MFPN      : fstrcat(typestr, "Mfp "); break;
+                                       case SV_TYPE_SERVER_NT        : fstrcat(typestr, "SNT "); break;
+                                       case SV_TYPE_POTENTIAL_BROWSER: fstrcat(typestr, "PtB "); break;
+                                       case SV_TYPE_BACKUP_BROWSER   : fstrcat(typestr, "BMB "); break;
+                                       case SV_TYPE_MASTER_BROWSER   : fstrcat(typestr, "LMB "); break;
+                                       case SV_TYPE_DOMAIN_MASTER    : fstrcat(typestr, "DMB "); break;
+                                       case SV_TYPE_SERVER_OSF       : fstrcat(typestr, "OSF "); break;
+                                       case SV_TYPE_SERVER_VMS       : fstrcat(typestr, "VMS "); break;
+                                       case SV_TYPE_WIN95_PLUS       : fstrcat(typestr, "W95 "); break;
+                                       case SV_TYPE_ALTERNATE_XPORT  : fstrcat(typestr, "Xpt "); break;
+                                       case SV_TYPE_LOCAL_LIST_ONLY  : fstrcat(typestr, "Dom "); break;
+                                       case SV_TYPE_DOMAIN_ENUM      : fstrcat(typestr, "Loc "); break;
+                               }
+                       }
+               }
+               i = strlen(typestr)-1;
+               if (typestr[i] == ' ') typestr[i] = 0;
+
+       }
+       return typestr;
+}
+
+/****************************************************************************
+server info level 101 display function
+****************************************************************************/
+void display_srv_info_101(FILE *out_hnd, enum action_type action,
+               SRV_INFO_101 *sv101)
+{
+       if (sv101 == NULL)
+       {
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "Server Info Level 101:\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring name;
+                       fstring comment;
+
+                       fstrcpy(name    , unistrn2(sv101->uni_name    .buffer, sv101->uni_name    .uni_str_len));
+                       fstrcpy(comment , unistrn2(sv101->uni_comment .buffer, sv101->uni_comment .uni_str_len));
+
+                       display_server(out_hnd, action, name, sv101->srv_type, comment);
+
+                       fprintf(out_hnd, "\tplatform_id     : %d\n"    , sv101->platform_id);
+                       fprintf(out_hnd, "\tos version      : %d.%d\n" , sv101->ver_major, sv101->ver_minor);
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+
+}
+
+/****************************************************************************
+server info level 102 display function
+****************************************************************************/
+void display_srv_info_102(FILE *out_hnd, enum action_type action,SRV_INFO_102 *sv102)
+{
+       if (sv102 == NULL)
+       {
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "Server Info Level 102:\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring name;
+                       fstring comment;
+                       fstring usr_path;
+
+                       fstrcpy(name    , unistrn2(sv102->uni_name    .buffer, sv102->uni_name    .uni_str_len));
+                       fstrcpy(comment , unistrn2(sv102->uni_comment .buffer, sv102->uni_comment .uni_str_len));
+                       fstrcpy(usr_path, unistrn2(sv102->uni_usr_path.buffer, sv102->uni_usr_path.uni_str_len));
+
+                       display_server(out_hnd, action, name, sv102->srv_type, comment);
+
+                       fprintf(out_hnd, "\tplatform_id     : %d\n"    , sv102->platform_id);
+                       fprintf(out_hnd, "\tos version      : %d.%d\n" , sv102->ver_major, sv102->ver_minor);
+
+                       fprintf(out_hnd, "\tusers           : %x\n"    , sv102->users      );
+                       fprintf(out_hnd, "\tdisc, hidden    : %x,%x\n" , sv102->disc     , sv102->hidden   );
+                       fprintf(out_hnd, "\tannounce, delta : %d, %d\n", sv102->announce , sv102->ann_delta);
+                       fprintf(out_hnd, "\tlicenses        : %d\n"    , sv102->licenses   );
+                       fprintf(out_hnd, "\tuser path       : %s\n"    , usr_path);
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+server info container display function
+****************************************************************************/
+void display_srv_info_ctr(FILE *out_hnd, enum action_type action,SRV_INFO_CTR *ctr)
+{
+       if (ctr == NULL || ctr->ptr_srv_ctr == 0)
+       {
+               fprintf(out_hnd, "Server Information: unavailable due to an error\n");
+               return;
+       }
+
+       switch (ctr->switch_value)
+       {
+               case 101:
+               {
+                       display_srv_info_101(out_hnd, action, &(ctr->srv.sv101));
+                       break;
+               }
+               case 102:
+               {
+                       display_srv_info_102(out_hnd, action, &(ctr->srv.sv102));
+                       break;
+               }
+               default:
+               {
+                       fprintf(out_hnd, "Server Information: Unknown Info Level\n");
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+connection info level 0 display function
+****************************************************************************/
+void display_conn_info_0(FILE *out_hnd, enum action_type action,
+               CONN_INFO_0 *info0)
+{
+       if (info0 == NULL)
+       {
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "Connection Info Level 0:\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\tid: %d\n", info0->id);
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+
+}
+
+/****************************************************************************
+connection info level 1 display function
+****************************************************************************/
+void display_conn_info_1(FILE *out_hnd, enum action_type action,
+               CONN_INFO_1 *info1, CONN_INFO_1_STR *str1)
+{
+       if (info1 == NULL || str1 == NULL)
+       {
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "Connection Info Level 1:\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring usr_name;
+                       fstring net_name;
+
+                       fstrcpy(usr_name, unistrn2(str1->uni_usr_name.buffer, str1->uni_usr_name.uni_str_len));
+                       fstrcpy(net_name, unistrn2(str1->uni_net_name.buffer, str1->uni_net_name.uni_str_len));
+
+                       fprintf(out_hnd, "\tid       : %d\n", info1->id);
+                       fprintf(out_hnd, "\ttype     : %s\n", get_share_type_str(info1->type));
+                       fprintf(out_hnd, "\tnum_opens: %d\n", info1->num_opens);
+                       fprintf(out_hnd, "\tnum_users: %d\n", info1->num_users);
+                       fprintf(out_hnd, "\topen_time: %d\n", info1->open_time);
+
+                       fprintf(out_hnd, "\tuser name: %s\n", usr_name);
+                       fprintf(out_hnd, "\tnet  name: %s\n", net_name);
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+
+}
+
+/****************************************************************************
+connection info level 0 container display function
+****************************************************************************/
+void display_srv_conn_info_0_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_CONN_INFO_0 *ctr)
+{
+       if (ctr == NULL)
+       {
+               fprintf(out_hnd, "display_srv_conn_info_0_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       int i;
+
+                       for (i = 0; i < ctr->num_entries_read; i++)
+                       {
+                               display_conn_info_0(out_hnd, ACTION_HEADER   , &(ctr->info_0[i]));
+                               display_conn_info_0(out_hnd, ACTION_ENUMERATE, &(ctr->info_0[i]));
+                               display_conn_info_0(out_hnd, ACTION_FOOTER   , &(ctr->info_0[i]));
+                       }
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+connection info level 1 container display function
+****************************************************************************/
+void display_srv_conn_info_1_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_CONN_INFO_1 *ctr)
+{
+       if (ctr == NULL)
+       {
+               fprintf(out_hnd, "display_srv_conn_info_1_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       int i;
+
+                       for (i = 0; i < ctr->num_entries_read; i++)
+                       {
+                               display_conn_info_1(out_hnd, ACTION_HEADER   , &(ctr->info_1[i]), &(ctr->info_1_str[i]));
+                               display_conn_info_1(out_hnd, ACTION_ENUMERATE, &(ctr->info_1[i]), &(ctr->info_1_str[i]));
+                               display_conn_info_1(out_hnd, ACTION_FOOTER   , &(ctr->info_1[i]), &(ctr->info_1_str[i]));
+                       }
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+connection info container display function
+****************************************************************************/
+void display_srv_conn_info_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_CONN_INFO_CTR *ctr)
+{
+       if (ctr == NULL || ctr->ptr_conn_ctr == 0)
+       {
+               fprintf(out_hnd, "display_srv_conn_info_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (ctr->switch_value)
+       {
+               case 0:
+               {
+                       display_srv_conn_info_0_ctr(out_hnd, action,
+                                          &(ctr->conn.info0));
+                       break;
+               }
+               case 1:
+               {
+                       display_srv_conn_info_1_ctr(out_hnd, action,
+                                          &(ctr->conn.info1));
+                       break;
+               }
+               default:
+               {
+                       fprintf(out_hnd, "display_srv_conn_info_ctr: Unknown Info Level\n");
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+share info level 1 display function
+****************************************************************************/
+void display_share_info_1(FILE *out_hnd, enum action_type action,
+               SH_INFO_1 *info1, SH_INFO_1_STR *str1)
+{
+       if (info1 == NULL || str1 == NULL)
+       {
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "Share Info Level 1:\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring remark  ;
+                       fstring net_name;
+
+                       fstrcpy(net_name, unistrn2(str1->uni_netname.buffer, str1->uni_netname.uni_str_len));
+                       fstrcpy(remark  , unistrn2(str1->uni_remark .buffer, str1->uni_remark .uni_str_len));
+
+                       display_share(out_hnd, action, net_name, info1->type, remark);
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+
+}
+
+/****************************************************************************
+share info level 2 display function
+****************************************************************************/
+void display_share_info_2(FILE *out_hnd, enum action_type action,
+               SH_INFO_2 *info2, SH_INFO_2_STR *str2)
+{
+       if (info2 == NULL || str2 == NULL)
+       {
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "Share Info Level 2:\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring remark  ;
+                       fstring net_name;
+                       fstring path    ;
+                       fstring passwd  ;
+
+                       fstrcpy(net_name, unistrn2(str2->uni_netname.buffer, str2->uni_netname.uni_str_len));
+                       fstrcpy(remark  , unistrn2(str2->uni_remark .buffer, str2->uni_remark .uni_str_len));
+                       fstrcpy(path    , unistrn2(str2->uni_path   .buffer, str2->uni_path   .uni_str_len));
+                       fstrcpy(passwd  , unistrn2(str2->uni_passwd .buffer, str2->uni_passwd .uni_str_len));
+
+                       display_share2(out_hnd, action, net_name, info2->type, remark,
+                                                             info2->perms, info2->max_uses, info2->num_uses,
+                                                             path, passwd);
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+
+}
+
+/****************************************************************************
+share info level 1 container display function
+****************************************************************************/
+void display_srv_share_info_1_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_SHARE_INFO_1 *ctr)
+{
+       if (ctr == NULL)
+       {
+               fprintf(out_hnd, "display_srv_share_info_1_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       int i;
+
+                       for (i = 0; i < ctr->num_entries_read; i++)
+                       {
+                               display_share_info_1(out_hnd, ACTION_HEADER   , &(ctr->info_1[i]), &(ctr->info_1_str[i]));
+                               display_share_info_1(out_hnd, ACTION_ENUMERATE, &(ctr->info_1[i]), &(ctr->info_1_str[i]));
+                               display_share_info_1(out_hnd, ACTION_FOOTER   , &(ctr->info_1[i]), &(ctr->info_1_str[i]));
+                       }
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+share info level 2 container display function
+****************************************************************************/
+void display_srv_share_info_2_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_SHARE_INFO_2 *ctr)
+{
+       if (ctr == NULL)
+       {
+               fprintf(out_hnd, "display_srv_share_info_2_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       int i;
+
+                       for (i = 0; i < ctr->num_entries_read; i++)
+                       {
+                               display_share_info_2(out_hnd, ACTION_HEADER   , &(ctr->info_2[i]), &(ctr->info_2_str[i]));
+                               display_share_info_2(out_hnd, ACTION_ENUMERATE, &(ctr->info_2[i]), &(ctr->info_2_str[i]));
+                               display_share_info_2(out_hnd, ACTION_FOOTER   , &(ctr->info_2[i]), &(ctr->info_2_str[i]));
+                       }
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+share info container display function
+****************************************************************************/
+void display_srv_share_info_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_SHARE_INFO_CTR *ctr)
+{
+       if (ctr == NULL || ctr->ptr_share_ctr == 0)
+       {
+               fprintf(out_hnd, "display_srv_share_info_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (ctr->switch_value)
+       {
+               case 1:
+               {
+                       display_srv_share_info_1_ctr(out_hnd, action,
+                                          &(ctr->share.info1));
+                       break;
+               }
+               case 2:
+               {
+                       display_srv_share_info_2_ctr(out_hnd, action,
+                                          &(ctr->share.info2));
+                       break;
+               }
+               default:
+               {
+                       fprintf(out_hnd, "display_srv_share_info_ctr: Unknown Info Level\n");
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+file info level 3 display function
+****************************************************************************/
+void display_file_info_3(FILE *out_hnd, enum action_type action,
+               FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
+{
+       if (info3 == NULL || str3 == NULL)
+       {
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "File Info Level 3:\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring path_name;
+                       fstring user_name;
+
+                       fstrcpy(path_name, unistrn2(str3->uni_path_name.buffer, str3->uni_path_name.uni_str_len));
+                       fstrcpy(user_name, unistrn2(str3->uni_user_name.buffer, str3->uni_user_name.uni_str_len));
+
+                       fprintf(out_hnd, "\tid       : %d\n", info3->id);
+                       fprintf(out_hnd, "\tperms    : %s\n", get_file_mode_str(info3->perms));
+                       fprintf(out_hnd, "\tnum_locks: %d\n", info3->num_locks);
+
+                       fprintf(out_hnd, "\tpath name: %s\n", path_name);
+                       fprintf(out_hnd, "\tuser name: %s\n", user_name);
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+
+}
+
+/****************************************************************************
+file info level 3 container display function
+****************************************************************************/
+void display_srv_file_info_3_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_FILE_INFO_3 *ctr)
+{
+       if (ctr == NULL)
+       {
+               fprintf(out_hnd, "display_srv_file_info_3_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       int i;
+
+                       for (i = 0; i < ctr->num_entries_read; i++)
+                       {
+                               display_file_info_3(out_hnd, ACTION_HEADER   , &(ctr->info_3[i]), &(ctr->info_3_str[i]));
+                               display_file_info_3(out_hnd, ACTION_ENUMERATE, &(ctr->info_3[i]), &(ctr->info_3_str[i]));
+                               display_file_info_3(out_hnd, ACTION_FOOTER   , &(ctr->info_3[i]), &(ctr->info_3_str[i]));
+                       }
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+file info container display function
+****************************************************************************/
+void display_srv_file_info_ctr(FILE *out_hnd, enum action_type action,
+                               SRV_FILE_INFO_CTR *ctr)
+{
+       if (ctr == NULL || ctr->ptr_file_ctr == 0)
+       {
+               fprintf(out_hnd, "display_srv_file_info_ctr: unavailable due to an internal error\n");
+               return;
+       }
+
+       switch (ctr->switch_value)
+       {
+               case 3:
+               {
+                       display_srv_file_info_3_ctr(out_hnd, action,
+                                          &(ctr->file.info3));
+                       break;
+               }
+               default:
+               {
+                       fprintf(out_hnd, "display_srv_file_info_ctr: Unknown Info Level\n");
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+ print browse connection on a host
+ ****************************************************************************/
+void display_server(FILE *out_hnd, enum action_type action,
+                               char *sname, uint32 type, char *comment)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\t%-15.15s%-20s %s\n",
+                                        sname, get_server_type_str(type), comment);
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+print shares on a host
+****************************************************************************/
+void display_share(FILE *out_hnd, enum action_type action,
+                               char *sname, uint32 type, char *comment)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\t%-15.15s%-10.10s%s\n",
+                                        sname, get_share_type_str(type), comment);
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+print shares on a host, level 2
+****************************************************************************/
+void display_share2(FILE *out_hnd, enum action_type action,
+                               char *sname, uint32 type, char *comment,
+                               uint32 perms, uint32 max_uses, uint32 num_uses,
+                               char *path, char *passwd)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\t%-15.15s%-10.10s%s %x %x %x %s %s\n",
+                                        sname, get_share_type_str(type), comment,
+                                        perms, max_uses, num_uses, path, passwd);
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+print name info
+****************************************************************************/
+void display_name(FILE *out_hnd, enum action_type action,
+                               char *sname)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\t%-21.21s\n", sname);
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+ display group rid info
+ ****************************************************************************/
+void display_group_rid_info(FILE *out_hnd, enum action_type action,
+                               uint32 num_gids, DOM_GID *gid)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       if (num_gids == 0)
+                       {
+                               fprintf(out_hnd, "\tNo Groups\n");
+                       }
+                       else
+                       {
+                               fprintf(out_hnd, "\tGroup Info\n");
+                               fprintf(out_hnd, "\t----------\n");
+                       }
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       int i;
+
+                       for (i = 0; i < num_gids; i++)
+                       {
+                               fprintf(out_hnd, "\tGroup RID: %8x attr: %x\n",
+                                                                 gid[i].g_rid, gid[i].attr);
+                       }
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+ display alias name info
+ ****************************************************************************/
+void display_alias_name_info(FILE *out_hnd, enum action_type action,
+                               uint32 num_aliases, fstring *alias_name, uint32 *num_als_usrs)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       if (num_aliases == 0)
+                       {
+                               fprintf(out_hnd, "\tNo Aliases\n");
+                       }
+                       else
+                       {
+                               fprintf(out_hnd, "\tAlias Names\n");
+                               fprintf(out_hnd, "\t----------- \n");
+                       }
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       int i;
+
+                       for (i = 0; i < num_aliases; i++)
+                       {
+                               fprintf(out_hnd, "\tAlias Name: %s Attributes: %3d\n",
+                                                                 alias_name[i], num_als_usrs[i]);
+                       }
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+ display sam_user_info_21 structure
+ ****************************************************************************/
+void display_sam_user_info_21(FILE *out_hnd, enum action_type action, SAM_USER_INFO_21 *usr)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "\tUser Info, Level 0x15\n");
+                       fprintf(out_hnd, "\t---------------------\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\t\tUser Name   : %s\n", unistrn2(usr->uni_user_name   .buffer, usr->uni_user_name   .uni_str_len)); /* username unicode string */
+                       fprintf(out_hnd, "\t\tFull Name   : %s\n", unistrn2(usr->uni_full_name   .buffer, usr->uni_full_name   .uni_str_len)); /* user's full name unicode string */
+                       fprintf(out_hnd, "\t\tHome Drive  : %s\n", unistrn2(usr->uni_home_dir    .buffer, usr->uni_home_dir    .uni_str_len)); /* home directory unicode string */
+                       fprintf(out_hnd, "\t\tDir Drive   : %s\n", unistrn2(usr->uni_dir_drive   .buffer, usr->uni_dir_drive   .uni_str_len)); /* home directory drive unicode string */
+                       fprintf(out_hnd, "\t\tProfile Path: %s\n", unistrn2(usr->uni_profile_path.buffer, usr->uni_profile_path.uni_str_len)); /* profile path unicode string */
+                       fprintf(out_hnd, "\t\tLogon Script: %s\n", unistrn2(usr->uni_logon_script.buffer, usr->uni_logon_script.uni_str_len)); /* logon script unicode string */
+                       fprintf(out_hnd, "\t\tDescription : %s\n", unistrn2(usr->uni_acct_desc   .buffer, usr->uni_acct_desc   .uni_str_len)); /* user description unicode string */
+                       fprintf(out_hnd, "\t\tWorkstations: %s\n", unistrn2(usr->uni_workstations.buffer, usr->uni_workstations.uni_str_len)); /* workstaions unicode string */
+                       fprintf(out_hnd, "\t\tUnknown Str : %s\n", unistrn2(usr->uni_unknown_str .buffer, usr->uni_unknown_str .uni_str_len)); /* unknown string unicode string */
+                       fprintf(out_hnd, "\t\tRemote Dial : %s\n", unistrn2(usr->uni_munged_dial .buffer, usr->uni_munged_dial .uni_str_len)); /* munged remote access unicode string */
+
+                       fprintf(out_hnd, "\t\tLogon Time               : %s\n", http_timestring(nt_time_to_unix(&(usr->logon_time           ))));
+                       fprintf(out_hnd, "\t\tLogoff Time              : %s\n", http_timestring(nt_time_to_unix(&(usr->logoff_time          ))));
+                       fprintf(out_hnd, "\t\tKickoff Time             : %s\n", http_timestring(nt_time_to_unix(&(usr->kickoff_time         ))));
+                       fprintf(out_hnd, "\t\tPassword last set Time   : %s\n", http_timestring(nt_time_to_unix(&(usr->pass_last_set_time   ))));
+                       fprintf(out_hnd, "\t\tPassword can change Time : %s\n", http_timestring(nt_time_to_unix(&(usr->pass_can_change_time ))));
+                       fprintf(out_hnd, "\t\tPassword must change Time: %s\n", http_timestring(nt_time_to_unix(&(usr->pass_must_change_time))));
+                       
+                       fprintf(out_hnd, "\t\tunknown_2[0..31]...\n"); /* user passwords? */
+
+                       fprintf(out_hnd, "\t\tuser_rid : %x\n"  , usr->user_rid ); /* User ID */
+                       fprintf(out_hnd, "\t\tgroup_rid: %x\n"  , usr->group_rid); /* Group ID */
+                       fprintf(out_hnd, "\t\tacb_info : %04x\n", usr->acb_info ); /* Account Control Info */
+
+                       fprintf(out_hnd, "\t\tunknown_3: %08x\n", usr->unknown_3); /* 0x00ff ffff */
+                       fprintf(out_hnd, "\t\tlogon_divs: %d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
+                       fprintf(out_hnd, "\t\tunknown_5: %08x\n", usr->unknown_5); /* 0x0002 0000 */
+
+                       fprintf(out_hnd, "\t\tpadding1[0..7]...\n");
+
+                       if (usr->ptr_logon_hrs)
+                       {
+                               fprintf(out_hnd, "\t\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len);
+                       }
+
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+}
+
+
+/****************************************************************************
+convert a security permissions into a string
+****************************************************************************/
+char *get_sec_mask_str(uint32 type)
+{
+       static fstring typestr;
+       int i;
+
+       switch (type)
+       {
+               case SEC_RIGHTS_FULL_CONTROL:
+               {
+                       fstrcpy(typestr, "Full Control");
+                       return typestr;
+               }
+
+               case SEC_RIGHTS_READ:
+               {
+                       fstrcpy(typestr, "Read");
+                       return typestr;
+               }
+               default:
+               {
+                       break;
+               }
+       }
+
+       typestr[0] = 0;
+       for (i = 0; i < 32; i++)
+       {
+               if (IS_BITS_SET_ALL(type, 1 << i))
+               {
+                       switch (1 << i)
+                       {
+                               case SEC_RIGHTS_QUERY_VALUE    : fstrcat(typestr, "Query " ); break;
+                               case SEC_RIGHTS_SET_VALUE      : fstrcat(typestr, "Set " ); break;
+                               case SEC_RIGHTS_CREATE_SUBKEY  : fstrcat(typestr, "Create "); break;
+                               case SEC_RIGHTS_ENUM_SUBKEYS   : fstrcat(typestr, "Enum "); break;
+                               case SEC_RIGHTS_NOTIFY         : fstrcat(typestr, "Notify "); break;
+                               case SEC_RIGHTS_CREATE_LINK    : fstrcat(typestr, "CreateLink "); break;
+                               case SEC_RIGHTS_DELETE         : fstrcat(typestr, "Delete "); break;
+                               case SEC_RIGHTS_READ_CONTROL   : fstrcat(typestr, "ReadControl "); break;
+                               case SEC_RIGHTS_WRITE_DAC      : fstrcat(typestr, "WriteDAC "); break;
+                               case SEC_RIGHTS_WRITE_OWNER    : fstrcat(typestr, "WriteOwner "); break;
+                       }
+                       type &= ~(1 << i);
+               }
+       }
+
+       /* remaining bits get added on as-is */
+       if (type != 0)
+       {
+               fstring tmp;
+               slprintf(tmp, sizeof(tmp)-1, "[%08x]", type);
+               fstrcat(typestr, tmp);
+       }
+
+       /* remove last space */
+       i = strlen(typestr)-1;
+       if (typestr[i] == ' ') typestr[i] = 0;
+
+       return typestr;
+}
+
+/****************************************************************************
+ display sec_access structure
+ ****************************************************************************/
+void display_sec_access(FILE *out_hnd, enum action_type action, SEC_ACCESS *info)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\t\tPermissions: %s\n",
+                               get_sec_mask_str(info->mask));
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+ display sec_ace structure
+ ****************************************************************************/
+void display_sec_ace(FILE *out_hnd, enum action_type action, SEC_ACE *ace)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "\tACE\n");
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring sid_str;
+
+                       display_sec_access(out_hnd, ACTION_HEADER   , &ace->info);
+                       display_sec_access(out_hnd, ACTION_ENUMERATE, &ace->info);
+                       display_sec_access(out_hnd, ACTION_FOOTER   , &ace->info);
+
+                       sid_to_string(sid_str, &ace->sid);
+                       fprintf(out_hnd, "\t\tSID: %s\n", sid_str);
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+ display sec_acl structure
+ ****************************************************************************/
+void display_sec_acl(FILE *out_hnd, enum action_type action, SEC_ACL *sec_acl)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "\tACL\tNum ACEs:\t%d\trevision:\t%x\n",
+                                        sec_acl->num_aces, sec_acl->revision); 
+                       fprintf(out_hnd, "\t---\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       if (sec_acl->size != 0 && sec_acl->num_aces != 0)
+                       {
+                               int i;
+                               for (i = 0; i < sec_acl->num_aces; i++)
+                               {
+                                       display_sec_ace(out_hnd, ACTION_HEADER   , &sec_acl->ace_list[i]);
+                                       display_sec_ace(out_hnd, ACTION_ENUMERATE, &sec_acl->ace_list[i]);
+                                       display_sec_ace(out_hnd, ACTION_FOOTER   , &sec_acl->ace_list[i]);
+                               }
+                       }
+                               
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+ display sec_desc structure
+ ****************************************************************************/
+void display_sec_desc(FILE *out_hnd, enum action_type action, SEC_DESC *sec)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "\tSecurity Descriptor\trevision:\t%x\ttype:\t%x\n",
+                                        sec->revision, sec->type); 
+                       fprintf(out_hnd, "\t-------------------\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fstring sid_str;
+
+                       if (sec->off_sacl != 0)
+                       {
+                               display_sec_acl(out_hnd, ACTION_HEADER   , sec->sacl);
+                               display_sec_acl(out_hnd, ACTION_ENUMERATE, sec->sacl);
+                               display_sec_acl(out_hnd, ACTION_FOOTER   , sec->sacl);
+                       }
+                       if (sec->off_dacl != 0)
+                       {
+                               display_sec_acl(out_hnd, ACTION_HEADER   , sec->dacl);
+                               display_sec_acl(out_hnd, ACTION_ENUMERATE, sec->dacl);
+                               display_sec_acl(out_hnd, ACTION_FOOTER   , sec->dacl);
+                       }
+                       if (sec->off_owner_sid != 0)
+                       {
+                               sid_to_string(sid_str, sec->owner_sid);
+                               fprintf(out_hnd, "\tOwner SID:\t%s\n", sid_str);
+                       }
+                       if (sec->off_grp_sid != 0)
+                       {
+                               sid_to_string(sid_str, sec->grp_sid);
+                               fprintf(out_hnd, "\tParent SID:\t%s\n", sid_str);
+                       }
+                               
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+convert a security permissions into a string
+****************************************************************************/
+char *get_reg_val_type_str(uint32 type)
+{
+       static fstring typestr;
+
+       switch (type)
+       {
+               case 0x01:
+               {
+                       fstrcpy(typestr, "string");
+                       return typestr;
+               }
+
+               case 0x03:
+               {
+                       fstrcpy(typestr, "bytes");
+                       return typestr;
+               }
+
+               case 0x04:
+               {
+                       fstrcpy(typestr, "uint32");
+                       return typestr;
+               }
+
+               case 0x07:
+               {
+                       fstrcpy(typestr, "multi");
+                       return typestr;
+               }
+               default:
+               {
+                       break;
+               }
+       }
+       slprintf(typestr, sizeof(typestr)-1, "[%d]", type);
+       return typestr;
+}
+
+
+static void print_reg_value(FILE *out_hnd, char *val_name, uint32 val_type, BUFFER2 *value)
+{
+       fstring type;
+       fstrcpy(type, get_reg_val_type_str(val_type));
+
+       switch (val_type)
+       {
+               case 0x01: /* unistr */
+               {
+                       fprintf(out_hnd,"\t%s:\t%s:\t%s\n", val_name, type, buffer2_to_str(value));
+                       break;
+               }
+
+               default: /* unknown */
+               case 0x03: /* bytes */
+               {
+                       if (value->buf_len <= 8)
+                       {
+                               fprintf(out_hnd,"\t%s:\t%s:\t", val_name, type);
+                               out_data(out_hnd, (char*)value->buffer, value->buf_len, 8);
+                       }
+                       else
+                       {
+                               fprintf(out_hnd,"\t%s:\t%s:\n", val_name, type);
+                               out_data(out_hnd, (char*)value->buffer, value->buf_len, 16);
+                       }
+                       break;
+               }
+
+               case 0x04: /* uint32 */
+               {
+                       fprintf(out_hnd,"\t%s:\t%s: 0x%08x\n", val_name, type, buffer2_to_uint32(value));
+                       break;
+               }
+
+               case 0x07: /* multiunistr */
+               {
+                       fprintf(out_hnd,"\t%s:\t%s:\t%s\n", val_name, type, buffer2_to_multistr(value));
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+ display structure
+ ****************************************************************************/
+void display_reg_value_info(FILE *out_hnd, enum action_type action,
+                               char *val_name, uint32 val_type, BUFFER2 *value)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       print_reg_value(out_hnd, val_name, val_type, value);
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+/****************************************************************************
+ display structure
+ ****************************************************************************/
+void display_reg_key_info(FILE *out_hnd, enum action_type action,
+                               char *key_name, time_t key_mod_time)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       fprintf(out_hnd, "\t%s\t(%s)\n",
+                               key_name, http_timestring(key_mod_time));
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       break;
+               }
+       }
+}
+
+#if COPY_THIS_TEMPLATE
+/****************************************************************************
+ display structure
+ ****************************************************************************/
+ void display_(FILE *out_hnd, enum action_type action, *)
+{
+       switch (action)
+       {
+               case ACTION_HEADER:
+               {
+                       fprintf(out_hnd, "\t\n"); 
+                       fprintf(out_hnd, "\t-------------------\n");
+
+                       break;
+               }
+               case ACTION_ENUMERATE:
+               {
+                       break;
+               }
+               case ACTION_FOOTER:
+               {
+                       fprintf(out_hnd, "\n");
+                       break;
+               }
+       }
+}
+
+#endif
index 3db45c95c878edc61d0ebfc9f4293947af31480c..ee5a81d1ff2a357a4bc041fb68a21be67f6ebe43 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* removed in SAMBA_2_0 branch. */
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+#ifndef REGISTER
+#define REGISTER 0
+#endif
+
+extern pstring debugf;
+extern pstring scope;
+extern pstring global_myname;
+
+extern pstring user_socket_options;
+
+
+extern int DEBUGLEVEL;
+
+
+extern file_info def_finfo;
+
+#define CNV_LANG(s) dos2unix_format(s,False)
+#define CNV_INPUT(s) unix2dos_format(s,True)
+
+static int process_tok(fstring tok);
+static void cmd_help(struct client_info *info);
+static void cmd_quit(struct client_info *info);
+
+static struct cli_state smbcli;
+struct cli_state *smb_cli = &smbcli;
+
+FILE *out_hnd;
+
+/****************************************************************************
+initialise smb client structure
+****************************************************************************/
+void rpcclient_init(void)
+{
+       memset((char *)smb_cli, '\0', sizeof(smb_cli));
+       cli_initialise(smb_cli);
+       smb_cli->capabilities |= CAP_NT_SMBS | CAP_STATUS32;
+}
+
+/****************************************************************************
+make smb client connection
+****************************************************************************/
+static BOOL rpcclient_connect(struct client_info *info)
+{
+       struct nmb_name calling;
+       struct nmb_name called;
+
+       make_nmb_name(&called , dns_to_netbios_name(info->dest_host ), info->name_type, scope);
+       make_nmb_name(&calling, dns_to_netbios_name(info->myhostname), 0x0            , scope);
+
+       if (!cli_establish_connection(smb_cli, 
+                                 info->dest_host, &info->dest_ip, 
+                                 &calling, &called,
+                                 info->share, info->svc_type,
+                                 False, True))
+       {
+               DEBUG(0,("rpcclient_connect: connection failed\n"));
+               cli_shutdown(smb_cli);
+               return False;
+       }
+
+       return True;
+}
+
+/****************************************************************************
+stop the smb connection(s?)
+****************************************************************************/
+static void rpcclient_stop(void)
+{
+       cli_shutdown(smb_cli);
+}
+/****************************************************************************
+ This defines the commands supported by this client
+ ****************************************************************************/
+struct
+{
+  char *name;
+  void (*fn)(struct client_info*);
+  char *description;
+} commands[] = 
+{
+  {"regenum",    cmd_reg_enum,         "<keyname> Registry Enumeration (keys, values)"},
+  {"regdeletekey",cmd_reg_delete_key,  "<keyname> Registry Key Delete"},
+  {"regcreatekey",cmd_reg_create_key,  "<keyname> [keyclass] Registry Key Create"},
+  {"regquerykey",cmd_reg_query_key,    "<keyname> Registry Key Query"},
+  {"regdeleteval",cmd_reg_delete_val,  "<valname> Registry Value Delete"},
+  {"regcreateval",cmd_reg_create_val,  "<valname> <valtype> <value> Registry Key Create"},
+  {"reggetsec",  cmd_reg_get_key_sec,  "<keyname> Registry Key Security"},
+  {"regtestsec", cmd_reg_test_key_sec, "<keyname> Test Registry Key Security"},
+  {"ntlogin",    cmd_netlogon_login_test, "[username] [password] NT Domain login test"},
+  {"wksinfo",    cmd_wks_query_info,   "Workstation Query Info"},
+  {"srvinfo",    cmd_srv_query_info,   "Server Query Info"},
+  {"srvsessions",cmd_srv_enum_sess,    "List sessions on a server"},
+  {"srvshares",  cmd_srv_enum_shares,  "List shares on a server"},
+  {"srvconnections",cmd_srv_enum_conn, "List connections on a server"},
+  {"srvfiles",   cmd_srv_enum_files,   "List files on a server"},
+  {"lsaquery",   cmd_lsa_query_info,   "Query Info Policy (domain member or server)"},
+  {"lookupsids", cmd_lsa_lookup_sids,  "Resolve names from SIDs"},
+  {"enumusers",  cmd_sam_enum_users,   "SAM User Database Query (experimental!)"},
+  {"ntpass",     cmd_sam_ntchange_pwd, "NT SAM Password Change"},
+  {"samuser",    cmd_sam_query_user,   "<username> SAM User Query (experimental!)"},
+  {"samtest",    cmd_sam_test      ,   "SAM User Encrypted RPC test (experimental!)"},
+  {"enumaliases",cmd_sam_enum_aliases, "SAM Aliases Database Query (experimental!)"},
+#if 0
+  {"enumgroups", cmd_sam_enum_groups,  "SAM Group Database Query (experimental!)"},
+#endif
+  {"samgroups",  cmd_sam_query_groups, "SAM Group Database Query (experimental!)"},
+  {"quit",       cmd_quit,        "logoff the server"},
+  {"q",          cmd_quit,        "logoff the server"},
+  {"exit",       cmd_quit,        "logoff the server"},
+  {"bye",        cmd_quit,        "logoff the server"},
+  {"help",       cmd_help,        "[command] give help on a command"},
+  {"?",          cmd_help,        "[command] give help on a command"},
+  {"!",          NULL,            "run a shell command on the local system"},
+  {"",           NULL,            NULL}
+};
+
+
+/****************************************************************************
+do a (presumably graceful) quit...
+****************************************************************************/
+static void cmd_quit(struct client_info *info)
+{
+       rpcclient_stop();
+#ifdef MEM_MAN
+       {
+               extern FILE* dbf;
+               smb_mem_write_status(dbf);
+               smb_mem_write_errors(dbf);
+               smb_mem_write_verbose(dbf);
+       }
+#endif
+       exit(0);
+}
+
+/****************************************************************************
+help
+****************************************************************************/
+static void cmd_help(struct client_info *info)
+{
+  int i=0,j;
+  fstring buf;
+
+  if (next_token(NULL,buf,NULL, sizeof(buf)))
+    {
+      if ((i = process_tok(buf)) >= 0)
+       fprintf(out_hnd, "HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description);                    
+    }
+  else
+    while (commands[i].description)
+      {
+       for (j=0; commands[i].description && (j<5); j++) {
+         fprintf(out_hnd, "%-15s",commands[i].name);
+         i++;
+       }
+       fprintf(out_hnd, "\n");
+      }
+}
+
+/*******************************************************************
+  lookup a command string in the list of commands, including 
+  abbreviations
+  ******************************************************************/
+static int process_tok(fstring tok)
+{
+  int i = 0, matches = 0;
+  int cmd=0;
+  int tok_len = strlen(tok);
+  
+  while (commands[i].fn != NULL)
+    {
+      if (strequal(commands[i].name,tok))
+       {
+         matches = 1;
+         cmd = i;
+         break;
+       }
+      else if (strnequal(commands[i].name, tok, tok_len))
+       {
+         matches++;
+         cmd = i;
+       }
+      i++;
+    }
+  
+  if (matches == 0)
+    return(-1);
+  else if (matches == 1)
+    return(cmd);
+  else
+    return(-2);
+}
+
+/****************************************************************************
+wait for keyboard activity, swallowing network packets
+****************************************************************************/
+static void wait_keyboard(struct cli_state *cli)
+{
+  fd_set fds;
+  struct timeval timeout;
+  
+  while (1) 
+    {
+      FD_ZERO(&fds);
+      FD_SET(cli->fd,&fds);
+      FD_SET(fileno(stdin),&fds);
+
+      timeout.tv_sec = 20;
+      timeout.tv_usec = 0;
+      sys_select(MAX(cli->fd,fileno(stdin))+1,&fds,&timeout);
+      
+      if (FD_ISSET(fileno(stdin),&fds))
+       return;
+
+      /* We deliberately use receive_smb instead of
+         client_receive_smb as we want to receive
+         session keepalives and then drop them here.
+       */
+      if (FD_ISSET(cli->fd,&fds))
+       receive_smb(cli->fd,cli->inbuf,0);
+    }  
+}
+
+/****************************************************************************
+  process commands from the client
+****************************************************************************/
+static void do_command(struct client_info *info, char *tok, char *line)
+{
+       int i;
+
+       if ((i = process_tok(tok)) >= 0)
+       {
+               commands[i].fn(info);
+       }
+       else if (i == -2)
+       {
+               fprintf(out_hnd, "%s: command abbreviation ambiguous\n", CNV_LANG(tok));
+       }
+       else
+       {
+               fprintf(out_hnd, "%s: command not found\n", CNV_LANG(tok));
+       }
+}
+
+/****************************************************************************
+  process commands from the client
+****************************************************************************/
+static BOOL process( struct client_info *info, char *cmd_str)
+{
+       pstring line;
+       char *cmd = cmd_str;
+
+       if (cmd[0] != '\0') while (cmd[0] != '\0')
+       {
+               char *p;
+               fstring tok;
+
+               if ((p = strchr(cmd, ';')) == 0)
+               {
+                       strncpy(line, cmd, 999);
+                       line[1000] = '\0';
+                       cmd += strlen(cmd);
+               }
+               else
+               {
+                       if (p - cmd > 999) p = cmd + 999;
+                       strncpy(line, cmd, p - cmd);
+                       line[p - cmd] = '\0';
+                       cmd = p + 1;
+               }
+
+               /* input language code to internal one */
+               CNV_INPUT (line);
+
+               /* get the first part of the command */
+               {
+                       char *ptr = line;
+                       if (!next_token(&ptr,tok,NULL, sizeof(tok))) continue;
+               }
+
+               do_command(info, tok, line);
+       }
+       else while (!feof(stdin))
+       {
+               fstring tok;
+
+               /* display a prompt */
+               fprintf(out_hnd, "smb: %s> ", CNV_LANG(info->cur_dir));
+               fflush(out_hnd);
+
+#ifdef CLIX
+               line[0] = wait_keyboard(smb_cli);
+               /* this might not be such a good idea... */
+               if ( line[0] == EOF)
+               {
+                       break;
+               }
+#else
+               wait_keyboard(smb_cli);
+#endif
+
+               /* and get a response */
+#ifdef CLIX
+               fgets( &line[1],999, stdin);
+#else
+               if (!fgets(line,1000,stdin))
+               {
+                       break;
+               }
+#endif
+
+               /* input language code to internal one */
+               CNV_INPUT (line);
+
+               /* special case - first char is ! */
+               if (*line == '!')
+               {
+                       system(line + 1);
+                       continue;
+               }
+
+               fprintf(out_hnd, "%s\n", line);
+
+               /* get the first part of the command */
+               {
+                       char *ptr = line;
+                       if (!next_token(&ptr,tok,NULL, sizeof(tok))) continue;
+               }
+
+               do_command(info, tok, line);
+       }
+
+       return(True);
+}
+
+/****************************************************************************
+usage on the program
+****************************************************************************/
+static void usage(char *pname)
+{
+  fprintf(out_hnd, "Usage: %s service <password> [-d debuglevel] [-l log] ",
+          pname);
+
+  fprintf(out_hnd, "\nVersion %s\n",VERSION);
+  fprintf(out_hnd, "\t-d debuglevel         set the debuglevel\n");
+  fprintf(out_hnd, "\t-l log basename.      Basename for log/debug files\n");
+  fprintf(out_hnd, "\t-n netbios name.      Use this name as my netbios name\n");
+  fprintf(out_hnd, "\t-N                    don't ask for a password\n");
+  fprintf(out_hnd, "\t-m max protocol       set the max protocol level\n");
+  fprintf(out_hnd, "\t-I dest IP            use this IP to connect to\n");
+  fprintf(out_hnd, "\t-E                    write messages to stderr instead of stdout\n");
+  fprintf(out_hnd, "\t-U username           set the network username\n");
+  fprintf(out_hnd, "\t-W workgroup          set the workgroup name\n");
+  fprintf(out_hnd, "\t-c command string     execute semicolon separated commands\n");
+  fprintf(out_hnd, "\t-t terminal code      terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n");
+  fprintf(out_hnd, "\n");
+}
+
+enum client_action
+{
+       CLIENT_NONE,
+       CLIENT_IPC,
+       CLIENT_SVC
+};
+
+/****************************************************************************
+  main program
+****************************************************************************/
+ int main(int argc,char *argv[])
+{
+       BOOL interactive = True;
+
+       int opt;
+       extern FILE *dbf;
+       extern char *optarg;
+       extern int optind;
+       static pstring servicesf = CONFIGFILE;
+       pstring term_code;
+       char *p;
+       BOOL got_pass = False;
+       char *cmd_str="";
+       mode_t myumask = 0755;
+       enum client_action cli_action = CLIENT_NONE;
+
+       struct client_info cli_info;
+
+       pstring password; /* local copy only, if one is entered */
+
+       out_hnd = stdout;
+       fstrcpy(debugf, argv[0]);
+
+       rpcclient_init();
+
+#ifdef KANJI
+       pstrcpy(term_code, KANJI);
+#else /* KANJI */
+       *term_code = 0;
+#endif /* KANJI */
+
+       DEBUGLEVEL = 2;
+
+       cli_info.put_total_size = 0;
+       cli_info.put_total_time_ms = 0;
+       cli_info.get_total_size = 0;
+       cli_info.get_total_time_ms = 0;
+
+       cli_info.dir_total = 0;
+       cli_info.newer_than = 0;
+       cli_info.archive_level = 0;
+       cli_info.print_mode = 1;
+
+       cli_info.translation = False;
+       cli_info.recurse_dir = False;
+       cli_info.lowercase = False;
+       cli_info.prompt = True;
+       cli_info.abort_mget = True;
+
+       cli_info.dest_ip.s_addr = 0;
+       cli_info.name_type = 0x20;
+
+       pstrcpy(cli_info.cur_dir , "\\");
+       pstrcpy(cli_info.file_sel, "");
+       pstrcpy(cli_info.base_dir, "");
+       pstrcpy(smb_cli->domain, "");
+       pstrcpy(smb_cli->user_name, "");
+       pstrcpy(cli_info.myhostname, "");
+       pstrcpy(cli_info.dest_host, "");
+
+       pstrcpy(cli_info.svc_type, "A:");
+       pstrcpy(cli_info.share, "");
+       pstrcpy(cli_info.service, "");
+
+       ZERO_STRUCT(cli_info.dom.level3_sid);
+       ZERO_STRUCT(cli_info.dom.level5_sid);
+       fstrcpy(cli_info.dom.level3_dom, "");
+       fstrcpy(cli_info.dom.level5_dom, "");
+
+       smb_cli->nt_pipe_fnum   = 0xffff;
+
+       TimeInit();
+       charset_initialise();
+
+       myumask = umask(0);
+       umask(myumask);
+
+       if (!get_myname(global_myname, NULL))
+       {
+               fprintf(stderr, "Failed to get my hostname.\n");
+       }
+
+       if (getenv("USER"))
+       {
+               pstrcpy(smb_cli->user_name,getenv("USER"));
+
+               /* modification to support userid%passwd syntax in the USER var
+               25.Aug.97, jdblair@uab.edu */
+
+               if ((p=strchr(smb_cli->user_name,'%')))
+               {
+                       *p = 0;
+                       pstrcpy(password,p+1);
+                       got_pass = True;
+                       memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
+               }
+               strupper(smb_cli->user_name);
+       }
+
+       password[0] = 0;
+
+       /* modification to support PASSWD environmental var
+          25.Aug.97, jdblair@uab.edu */
+       if (getenv("PASSWD"))
+       {
+               pstrcpy(password,getenv("PASSWD"));
+       }
+
+       if (*smb_cli->user_name == 0 && getenv("LOGNAME"))
+       {
+               pstrcpy(smb_cli->user_name,getenv("LOGNAME"));
+               strupper(smb_cli->user_name);
+       }
+
+       if (argc < 2)
+       {
+               usage(argv[0]);
+               exit(1);
+       }
+
+       if (*argv[1] != '-')
+       {
+
+               pstrcpy(cli_info.service, argv[1]);  
+               /* Convert any '/' characters in the service name to '\' characters */
+               string_replace( cli_info.service, '/','\\');
+               argc--;
+               argv++;
+
+               fprintf(out_hnd, "service: %s\n", cli_info.service);
+
+               if (count_chars(cli_info.service,'\\') < 3)
+               {
+                       usage(argv[0]);
+                       printf("\n%s: Not enough '\\' characters in service\n", cli_info.service);
+                       exit(1);
+               }
+
+               /*
+               if (count_chars(cli_info.service,'\\') > 3)
+               {
+                       usage(pname);
+                       printf("\n%s: Too many '\\' characters in service\n", cli_info.service);
+                       exit(1);
+               }
+               */
+
+               if (argc > 1 && (*argv[1] != '-'))
+               {
+                       got_pass = True;
+                       pstrcpy(password,argv[1]);  
+                       memset(argv[1],'X',strlen(argv[1]));
+                       argc--;
+                       argv++;
+               }
+
+               cli_action = CLIENT_SVC;
+       }
+
+       while ((opt = getopt(argc, argv,"s:B:O:M:S:i:N:n:d:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
+       {
+               switch (opt)
+               {
+                       case 'm':
+                       {
+                               /* FIXME ... max_protocol seems to be funny here */
+
+                               int max_protocol = 0;
+                               max_protocol = interpret_protocol(optarg,max_protocol);
+                               fprintf(stderr, "max protocol not currently supported\n");
+                               break;
+                       }
+
+                       case 'O':
+                       {
+                               pstrcpy(user_socket_options,optarg);
+                               break;  
+                       }
+
+                       case 'S':
+                       {
+                               pstrcpy(cli_info.dest_host,optarg);
+                               strupper(cli_info.dest_host);
+                               cli_action = CLIENT_IPC;
+                               break;
+                       }
+
+                       case 'B':
+                       {
+                               iface_set_default(NULL,optarg,NULL);
+                               break;
+                       }
+
+                       case 'i':
+                       {
+                               pstrcpy(scope, optarg);
+                               break;
+                       }
+
+                       case 'U':
+                       {
+                               char *lp;
+                               pstrcpy(smb_cli->user_name,optarg);
+                               if ((lp=strchr(smb_cli->user_name,'%')))
+                               {
+                                       *lp = 0;
+                                       pstrcpy(password,lp+1);
+                                       got_pass = True;
+                                       memset(strchr(optarg,'%')+1,'X',strlen(password));
+                               }
+                               break;
+                       }
+
+                       case 'W':
+                       {
+                               pstrcpy(smb_cli->domain,optarg);
+                               break;
+                       }
+
+                       case 'E':
+                       {
+                               dbf = stderr;
+                               break;
+                       }
+
+                       case 'I':
+                       {
+                               cli_info.dest_ip = *interpret_addr2(optarg);
+                               if (zero_ip(cli_info.dest_ip))
+                               {
+                                       exit(1);
+                               }
+                               break;
+                       }
+
+                       case 'n':
+                       {
+                               fstrcpy(global_myname, optarg);
+                               break;
+                       }
+
+                       case 'N':
+                       {
+                               got_pass = True;
+                               break;
+                       }
+
+                       case 'd':
+                       {
+                               if (*optarg == 'A')
+                                       DEBUGLEVEL = 10000;
+                               else
+                                       DEBUGLEVEL = atoi(optarg);
+                               break;
+                       }
+
+                       case 'l':
+                       {
+                               slprintf(debugf, sizeof(debugf)-1,
+                                        "%s.client", optarg);
+                               interactive = False;
+                               break;
+                       }
+
+                       case 'c':
+                       {
+                               cmd_str = optarg;
+                               got_pass = True;
+                               break;
+                       }
+
+                       case 'h':
+                       {
+                               usage(argv[0]);
+                               exit(0);
+                               break;
+                       }
+
+                       case 's':
+                       {
+                               pstrcpy(servicesf, optarg);
+                               break;
+                       }
+
+                       case 't':
+                       {
+                               pstrcpy(term_code, optarg);
+                               break;
+                       }
+
+                       default:
+                       {
+                               usage(argv[0]);
+                               exit(1);
+                               break;
+                       }
+               }
+       }
+
+       setup_logging(debugf, interactive);
+
+       if (cli_action == CLIENT_NONE)
+       {
+               usage(argv[0]);
+               exit(1);
+       }
+
+       strupper(global_myname);
+       fstrcpy(cli_info.myhostname, global_myname);
+
+       DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION));
+
+       if (!lp_load(servicesf,True, False, False))
+       {
+               fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
+       }
+
+       codepage_initialise(lp_client_code_page());
+
+       if (*smb_cli->domain == 0) pstrcpy(smb_cli->domain,lp_workgroup());
+
+       load_interfaces();
+
+       if (cli_action == CLIENT_IPC)
+       {
+               pstrcpy(cli_info.share, "IPC$");
+               pstrcpy(cli_info.svc_type, "IPC");
+       }
+
+       fstrcpy(cli_info.mach_acct, cli_info.myhostname);
+       strupper(cli_info.mach_acct);
+       fstrcat(cli_info.mach_acct, "$");
+
+       /* set the password cache info */
+       if (got_pass)
+       {
+               if (password[0] == 0)
+               {
+                       pwd_set_nullpwd(&(smb_cli->pwd));
+               }
+               else
+               {
+                       pwd_make_lm_nt_16(&(smb_cli->pwd), password); /* generate 16 byte hashes */
+               }
+       }
+       else 
+       {
+               pwd_read(&(smb_cli->pwd), "Enter Password:", True);
+       }
+
+       /* paranoia: destroy the local copy of the password */
+       memset((char *)password, '\0', sizeof(password)); 
+
+       /* establish connections.  nothing to stop these being re-established. */
+       rpcclient_connect(&cli_info);
+
+       DEBUG(5,("rpcclient_connect: smb_cli->fd:%d\n", smb_cli->fd));
+       if (smb_cli->fd <= 0)
+       {
+               fprintf(stderr, "warning: connection could not be established to %s<%02x>\n",
+                                cli_info.dest_host, cli_info.name_type);
+               fprintf(stderr, "this version of smbclient may crash if you proceed\n");
+               exit(-1);
+       }
+
+       switch (cli_action)
+       {
+               case CLIENT_IPC:
+               {
+                       process(&cli_info, cmd_str);
+                       break;
+               }
+
+               default:
+               {
+                       fprintf(stderr, "unknown client action requested\n");
+                       break;
+               }
+       }
+
+       rpcclient_stop();
+
+       return(0);
+}